|
[size=13.3333px]一 三种类型的套接字:
0 N8 p# ?/ g! n8 p; K1.流式套接字(SOCKET_STREAM), k' ], T& |7 U2 O( W" r
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。) \0 v4 q" h* Z$ y" a: X
2.数据报式套接字(SOCKET_DGRAM), |# v8 i" Q, `4 x* n7 ?. |
提供无连接的数据传输服务,不保证可靠性。
- P* I: t) k8 O& K- J3.原始式套接字(SOCKET_RAW)
" S! K3 p: }/ k$ h: N4 T& n" x 该接口允许对较低层次协议,如IP,ICMP直接访问。3 H1 u- H- P- ~- x7 c9 J1 `5 b$ z
" t( v! p/ m* r5 S. l" I9 ~
二 基本套接字系统调有有如下一些:2 ?+ f% W6 `5 z2 D( i: x
创建套接字: socket()) z0 T6 q# Y2 e% V' Y
绑定本机端口: bind()
/ C0 U8 Z8 Z' L 建立连接: connect(),accept()% i( q- A& V) w3 [; U3 O; T1 T* w" D
侦听端口: listen()
2 i E/ `; k! X; \; o 数据传输: send(), recv()
. x6 @ x, W: N" i, t 输入/输出多路复用: select()4 F2 k* B ?- N& D
关闭套接只: closesocket(). T# Q! j B6 b+ i( |0 S
e9 a4 @# H" r4 a1 P三 数据类型
( e' R# _2 U; I5 H+ R struct sockaddr# w6 Z0 O1 k0 _7 @( k
{
8 l* J% Y( R/ L& K) N9 O9 w5 n unsigned short sa_family; //地址族, 一般为AF_INET4 }: Q% E- M* M1 c: I% D( f! A
char sa_data[14]; //14字节的协议地址
; z/ y' Y% C" K/ m4 w1 ? }" G4 a/ W% H5 N8 m5 c4 R6 D* \
4 Z7 B" {! e" w8 _3 i
struct sockaddr_in
9 U2 Q |( c) U7 l" h* k {
0 ]/ k- {$ m5 G @8 b5 {9 j1 F short int sin_family; //地址族# C% N9 Q; U0 x) ^) \7 A- D c
unsigned short int sin_port; //端口号% j; j* S8 N# o$ N
struct in_addr in_addr; //ip地址
- c% N2 S8 D* y2 ` unsigned char sin_zero[8]; //填充
/ H0 u- q- j9 F" [& G7 Q }2 o5 m& k: ^; r& @# g* ?
# @# I; d2 c' O
四 常用函数
$ O/ F) k! w+ K 1 socket()5 \) T( {; g2 H3 ~# n; F. W
头文件:
9 ?! ~4 n9 m" f4 O( f, ^9 a #include <sys/types.h>4 a5 P4 A. I: n1 m$ \6 X
#include <sys/socket.h>
8 U/ K" t- K+ ? 函数原型:
8 Z; |. p6 P# w$ m( y9 H" M int socket(int domain, int type, int protocol)
6 I& T; |* ]7 c/ K5 K& n domain: 协议类型,一般为AF_INET" v, l: G0 d5 O' G2 T! Y' M
type: socket类型
: d! T) _( k2 ]; G9 l protocol:用来指定socket所使用的传输协议编号,通常设为0即可
2 Y0 ^* U7 m4 Q, i' S2 G& p5 A7 p i- ?4 {8 w3 u) H0 w4 w
2 bind()
/ z+ S' L' |! Y% R3 z 头文件:
: M! H8 A1 p/ f: @9 S. ` #include <sys/types.h>
: c9 s2 d" L7 J #include <sys/socket.h>! \, N% @4 |7 o2 G8 g# V
函数原型:6 S# A; }) [, U/ I5 b f
int bind(int sockfd, struct sockaddr *my_addr, int addrlen). T5 U; y1 q8 |5 {) e% c; n/ l
sockfd: socket描述符
0 j$ f2 V7 [6 ? my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
( Z h' K# U+ l- s5 U, {( G$ A* n addrlen:常被设为sizeof(struct sockaddr)
% l5 @& Q+ @" \' E1 u
) G3 b* Q7 {+ K 3 connect()& V( G6 c, h2 q6 H7 }+ Y: V1 ?5 U
头文件:
6 l5 K+ w# C! j2 A; O! E #include <sys/types.h> ) p! B+ }8 _. _( m7 \( _* W/ O- S
#include <sys/socket.h>
4 f8 I) S$ h2 j& y. h5 s- Z 函数原型:2 ?) n( e- [+ ~+ d
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)- X% n& |6 r; q; G4 [
sockfd: 目的服务器的socket描述符* \: n! h7 X% _1 e( x
serv_addr:包含目的机器ip地址和端口号的指针: `3 N& I' P7 c8 A8 V
addrlen:sizeof(struct sockaddr)
1 c) ^6 O+ X) x! ^/ w+ f: `
0 W9 K$ z! }/ S 4 listen()
' S/ Q: Q( I. y3 A3 U! s% e 头文件:
& d4 P8 I- c5 q M% R3 P: e7 I #include <sys/socket.h>: E9 h% E" b0 L( o
函数原型:
) A( `( q. o6 T) L3 |# L+ u int listen(int sockfd, int backlog);4 d' K) Q! _ @
sockfd:socket()系统调用返回的socket描述符
5 S$ n: \ E" ^5 d7 { backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。
) w, d, }) P0 e+ K: A. i
/ p: |9 e- D$ G8 Z1 k 5 accept()
0 r' c# t! R* M$ n" O4 M 头文件:
# p# M" N4 b( O; E& x #include <sys/types.h>; R. j( k3 r, A$ I
#inlcude <sys/socket.h>
0 k+ {8 z3 W" Q# ^ 函数原型:
7 \9 D% c9 I0 z& B int accept(int sockfd, void *addr, int addrlen)5 a, p$ e7 |1 Y8 c$ G& L% M
sockfd:是被监听的socket描述符' P9 H9 J0 Z9 F
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息2 B( n# w3 K" O2 H+ K! K
addrlen:sizeof(struct sockaddr_in)
6 F7 I( f, T' e. G6 @8 I 8 a; r4 l( }2 K5 H
6 send()$ F" W# M9 W9 C2 W; x/ O
头文件:4 e5 O: e6 m0 e
#include <sys/socket.h>- U+ M& M d& {' l& q! e
函数原型:& H9 k' N( q; i
int send(int sockfd, const void *msg, int len, int flags);
1 Y, g1 ?; Y& A0 M sockfd:用来传输数据的socket描述符3 n, [0 v5 R% L5 U3 p2 W
msg:要发送数据的指针
B5 v$ L5 j- \# |# L. S flags: 0
6 _. L. h# `0 O6 {! E, a
# M1 g( r7 `: P 7 recv(): N$ A! d* Q A
头文件:: ?" O3 S- A' T0 i& z% |0 Z( Q, v
#include <sys/types.h>
* t0 e8 B( B/ |: O9 u& D #include <sys/socket.h>
7 k& Z$ H! k _! c+ u) m 函数原型:; y% w& E" i4 ]' j
int recv(int sockfd, void *buf, int len, unsigned int flags)1 X3 K9 E( J1 V
sockfd:接收数据的socket描述符
! h% [) N$ r3 x7 `0 m: D buf:存放数据的缓冲区
* Z+ h F& {6 J, P, t' a" e len:缓冲的长度. _- E6 N- _: x! k9 a! K! V( s
flags:0, m/ m) Q" y( j+ q& A' s/ k
0 ], A9 @5 s: T. s. ]& D6 v7 G& O) E
8 sendto()" x) ~; u1 `. Z7 S
头文件:
' z9 M- F' k/ A! n9 T! Q #include <sys/types.h>
) V! K1 q& b! }7 h5 N6 e% k( X #include <sys/socket.h>
0 `" E, n# K. Z: \ 函数原型:
h4 H5 u* {0 J int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);2 I3 C2 F( ?! x
3 D" Q& y- C3 t; X; C2 X1 x& N
2 a) |2 z& t5 K$ U" V
9 recvfrom()& p* A# f( C4 |1 S0 _
头文件:
/ ^+ v& g; ~0 G, n: d4 N0 ^0 d6 } #include <sys/types.h>
" I" X9 L" L1 c; X. [1 B" n #include <sys/socket.h>) Y2 c" ?+ ]6 S9 m1 J0 A0 c- b
函数原型:" h% l5 X& P: t% X% f$ s8 e
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)
# Y* e! [( B7 e( f
2 Z2 \6 {8 ^. T ; I/ I: o, c& P$ |9 D5 \
10 read() write()
. R: _2 M, w* o8 V1 h int read(int fd, char *buf, int len)
# [) G# m' F/ O ~- J" u( `$ f int write(int fd, char *buf, int len)* S+ S: z) h( }4 Z* Y
' A- ^" S3 w2 v( p% p( R% f
11 shutdown()3 x+ X( W3 L+ E: Q" Q
close(sockfd), N2 r1 L# z, ^" _
int shutdown(int sockfd, int how)
( n$ b. H- q4 [% X----------------------------------- [size=13.3333px]netinet/if_ether.h ether_arp的数据结构 [size=13.3333px]netinet/ether.h 以太祯的网络字节和ascii字节的转换,包括ether_ntoa(),ether_aton这样的函数定义 [size=13.3333px]netinet/ip.h 这个头文件和linux/ip.h似乎很相似,也有iphdr的数据结构,同时还包括了timestamp结构,我的理解是,linux文件夹下的 ip.h是linux黑客编写的ip头文件,而这个则是gnu一开始就定义的头文件,同时还包括了bsd中的ipheader结构定义。同理的还有该目录 下的tcp.h等文件 [size=13.3333px]linux/ip.h iphdr的数据结构,以及一些ip层的数据定义,同理的还有tcp.h,udp.h等等 [size=13.3333px]linux/if.h 主要的socket头文件,似乎修改自unix的if.h,定义了网卡的接口信息的宏,例如IFF_UP.另外有数个重要的interface的数据结构定义,包括ifreq,ifconf,ifmap [size=13.3333px]linux/if_packet.h 原始数据包的数据结构定义,包括sockaddr_pkt,sockaddr_ll,想接收原始数据包的不能错过这个文件。同理的还有if_ppp.h,if_tun.h等等 [size=13.3333px]netinet/in.h 这个文件作的事情就多了。端口宏定义,著名ip(比如loopback),结构sockaddr_in,网络字节转换(ntoh,hton。。。。)。。。反正太多了,没事的话就把这个文件加到头文件包含里吧 [size=13.3333px]netdb.h 文件如其名,包括结构hostent(主机环境),获得主机的信息的几个函数(gethostbyname)。似乎这个就是定义主机的各项环境,例如hostname等等 [size=13.3333px]net/bpf.h berkeley的数据包过滤头文件,想用bpf进行包过滤的要重视一下这个文件 [size=13.3333px]net/ethernet.h 包括几个以太网的数据结构,ether_addr(mac帧结构),ether_header(以太帧的头部) [size=13.3333px]------------------------------- [size=13.3333px]<sys/types.h> //primitive system data types(包含很多类型重定义,如pid_t、int8_t等) ( Z% }) `- p( z9 p
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
3 P. ^9 C0 G# G. g<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()' L+ c. k4 u7 A" n0 U( V
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等" r0 a v+ D. @; B5 Y/ t
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
2 H) F$ x9 k3 t" U<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等, t" Y" N, C+ B
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件1 Y. e6 t6 Z: w" q4 }
7 Y& K; ~+ Z2 W: {[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
9 p$ Q( g- ~, p/ Y3 |#include <sys/types.h> 6 l3 i! x! b$ ^3 n5 q2 K+ u
9 D3 N1 Z( f w. K
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons9 H( N. u* j Z* l* N+ K. j
#include <poll.h> //poll,pollfd
- P F+ q) T+ f" g3 { B#include <arpa/inet.h> //inet_addr,inet_aton
. ?2 Q* P* X' z+ |#include <unistd.h> //read,write
$ w- k/ u; ?4 X( o! {1 v- P#include <netdb.h> //gethostbyname
3 a3 |: o- {& D1 F W9 ^
1 S# N, e% J$ ?6 Q( [, E! |#include <error.h> //perror
% C6 L& ~: K* v1 t. K6 I#include <stdio.h>
5 c3 a+ y( Q+ J% b P7 k#include <errno.h> //errno
8 i: J# b: A' O& s5 e, g, ~1 g% V4 o, ^
#include <string.h> // memset9 ?3 ]- Q; Q' A, l# |
#include <string>; _' ^" t! L3 w5 Z6 q
#include <iostream>4 C" @6 ~5 Q* s: L5 V. D$ L. \
% h! Z' j2 X: T* q. m0 L9 U9 C: n |