[size=13.3333px]一 三种类型的套接字:
- N, L" X4 p( m* o1.流式套接字(SOCKET_STREAM)
$ E4 W; n. I0 G. o 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
5 {" X% Z$ V" K7 }6 K2.数据报式套接字(SOCKET_DGRAM)) f4 `6 I# U7 S' x
提供无连接的数据传输服务,不保证可靠性。9 \5 u/ B i+ ]/ a
3.原始式套接字(SOCKET_RAW)% H0 Q0 v# _: w3 @
该接口允许对较低层次协议,如IP,ICMP直接访问。
# R. W* @3 F+ R3 J- B+ ?6 N# L$ n: m7 V
二 基本套接字系统调有有如下一些:
" L& A; B) g$ K) |5 c# Z 创建套接字: socket()
, O' g: d" R8 y5 G 绑定本机端口: bind()
/ D' @9 X4 G" }5 X% Y 建立连接: connect(),accept(): q! t; \( E/ V, k& ?9 F2 z# V
侦听端口: listen()* E7 {8 `! e4 b* i! Y0 I4 d( B4 s+ |
数据传输: send(), recv()7 U& w4 `+ _" V- J" j% ]
输入/输出多路复用: select()+ H5 |, ^5 H* A7 {2 [" |5 \0 N8 M
关闭套接只: closesocket() b5 E. n1 _* E1 u3 X3 [ v7 e- @
7 W9 ?$ x R/ s三 数据类型% A. F& z5 y! n
struct sockaddr
' I" p0 M# v& Q, b! ~+ ? C# C0 Q& } { R4 d9 ? J) `$ {9 p
unsigned short sa_family; //地址族, 一般为AF_INET L4 O- `+ R b7 U5 g% j* B: ~
char sa_data[14]; //14字节的协议地址0 s$ o3 V! e, E v
}
) J/ }3 v/ F3 [8 ~$ { B. ^. t( T/ H2 U3 f0 t( ^9 z% r
struct sockaddr_in
& q) v( ]! A0 f% W2 Y8 M {
" X" s3 f& G/ R* X# ?6 w% p! u( e5 A short int sin_family; //地址族& G q: W% p: D
unsigned short int sin_port; //端口号; J& a v! G; ~5 v6 V6 C
struct in_addr in_addr; //ip地址
* q/ h/ t9 R9 f# b, u unsigned char sin_zero[8]; //填充: Y5 _0 c( O/ a% \$ T. z R
}
( |: {9 X0 a% i# t1 q: c8 e% l. ?* A# O: T" y
四 常用函数
( G# a$ x; C S; K2 j; n. k 1 socket()
, m% H- o: K3 ?& z 头文件:
5 Y8 X+ S B: B; t1 d #include <sys/types.h>
8 E/ ^* B2 r/ n# b% Z. Y8 d9 t #include <sys/socket.h>
3 l+ r# c1 T, K" T- g 函数原型:
! @1 y$ a5 i2 Q6 D int socket(int domain, int type, int protocol)
# r" \- `" l# g% i# F: B* z0 T! J domain: 协议类型,一般为AF_INET/ E! r9 W& g+ {. n7 \
type: socket类型0 Q3 C9 t. j# b) S
protocol:用来指定socket所使用的传输协议编号,通常设为0即可* J- V3 T/ \# W) T! }' k
. j: e5 D; ^, R1 M& c
2 bind()
, y# W7 B" V( }; \# ]. T 头文件:- n3 l$ u4 k' x M
#include <sys/types.h>
6 _+ ? x* X8 X4 z& @ #include <sys/socket.h>: q7 o& u- H$ s8 n
函数原型:
9 ^) _9 t* N+ f$ I( K# f int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
" b& o8 Z! F0 M sockfd: socket描述符- C( P7 z" z( i3 n- f) Y
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
5 y( `, o5 X x) O+ b addrlen:常被设为sizeof(struct sockaddr)
" E5 K$ n$ v1 M) U$ t. r$ U- I0 q5 F8 p$ j K: N
3 connect()6 N0 O: [. T% z4 S* E2 J
头文件:
6 R# w& z' X! _ n7 ^0 x #include <sys/types.h>
/ O: R w0 Z) f1 C6 i. j #include <sys/socket.h>* U3 q! ^4 y7 h
函数原型:
, R0 A3 x3 G5 X7 h. i* f& |2 A8 A' v int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)/ x+ s( k3 V6 A- Z
sockfd: 目的服务器的socket描述符# }) q% o R5 I" m' ^5 `5 X
serv_addr:包含目的机器ip地址和端口号的指针4 p/ M0 y9 j: U8 E9 j
addrlen:sizeof(struct sockaddr)
s% o# _0 @% x) G5 m
+ j( T* D& F' B8 T! a/ M 4 listen()1 I; Y7 w2 t0 K4 R& @7 [1 M
头文件:: i, e3 ~6 x3 d4 Y+ s4 A- q' W' ?( O
#include <sys/socket.h>
& X/ r4 [/ n1 I2 W; k 函数原型:; w1 i# U% D& G$ @
int listen(int sockfd, int backlog);
' o( j* A0 }$ |% g/ E sockfd:socket()系统调用返回的socket描述符
% m' X) T! L6 M0 S backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。* k$ V- n" u& G" u
9 B9 }# r3 h7 i) O 5 accept()
9 m! ?: o" n# e% r' R/ H1 X+ J) }# F 头文件:
: n4 F/ Z: I9 c #include <sys/types.h>
3 v0 S- `+ r, _ #inlcude <sys/socket.h>
" t/ E8 F z1 V1 Q 函数原型:
; i2 N; e6 o" R int accept(int sockfd, void *addr, int addrlen)
% [6 c1 d; A! V! V' [: d! D+ d$ {- w sockfd:是被监听的socket描述符
2 i! V9 V' N& } Q- o1 ?; a! P addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息3 I0 Y5 C! l- W; N- L' I& T- [
addrlen:sizeof(struct sockaddr_in)
6 h. Y* W+ c% @
$ p& T& G: A% J0 [5 X. n6 W 6 send()
2 i2 V) {- E* ]- h! `8 S) n g 头文件:( }( ?3 m2 o2 c1 l/ N( E
#include <sys/socket.h>4 T7 _7 a7 @; N9 o( {4 h
函数原型:; ~1 `5 p) p1 C$ }2 c; Y
int send(int sockfd, const void *msg, int len, int flags);9 _: {( d) {. J
sockfd:用来传输数据的socket描述符$ c9 t/ X6 ~6 W9 O/ ~6 F& T
msg:要发送数据的指针
3 g I; v" u" b flags: 0
5 L3 N$ z& w! i3 R' R }3 m2 }; y , P" M: J: G! W/ s* h
7 recv()
: n7 S. h& Q+ p1 `2 g* z' J" F& s 头文件:+ M: V8 x' Z1 ?0 h% `* [" d
#include <sys/types.h>: D# A7 L8 b' A- I" `. j; j9 R
#include <sys/socket.h>/ {4 R2 |. X% ]$ ^! u/ m- {# ]
函数原型:
7 J3 W6 s2 k, l3 Y3 ]3 C. p+ j int recv(int sockfd, void *buf, int len, unsigned int flags)
0 G1 `, q/ l/ c( t( D$ y& p1 e sockfd:接收数据的socket描述符
7 I* X6 W q, k buf:存放数据的缓冲区$ n; s9 r& d' H/ t7 }
len:缓冲的长度
5 B/ S+ _8 b* G- F. E1 u4 r flags:0
) [. i6 b# c- [) K% `) a6 z$ T- L& n3 ^" ~# h
8 sendto()
1 H5 b9 O* \8 s! K 头文件:
) @4 k& u+ N- e# Z1 t #include <sys/types.h>
' `! J$ _3 v' A* u #include <sys/socket.h>
# ?9 |# c% z: {3 q; Q 函数原型:
. M) _0 W4 u7 f+ p int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
" j, s( i l% y V ) k" |; ~8 ^8 o- `4 A! H% _
" d5 ^" G& C: V& w 9 recvfrom()5 F8 V+ u7 H, }( l) z! z
头文件:
9 I5 S& r( @" T9 k1 b( B) B #include <sys/types.h>
& w# V& I* f* Z8 o+ p9 A #include <sys/socket.h> L }0 f$ t) J7 |# }5 B
函数原型:4 K O) U2 |' G! b& E4 T/ b8 \
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)
# G, W. m. l3 R. j4 m s3 p6 `' y( }, O! M8 z) C
" h" [- ?5 p5 I% H
10 read() write()( u- q) [8 V j2 U6 A
int read(int fd, char *buf, int len)
, c/ G% c/ L6 b3 H1 ?5 p int write(int fd, char *buf, int len)
8 h# R7 ^/ f' R; Q. B% P + V% m7 ^* r+ r8 V
11 shutdown()
2 w2 q; E9 W! D: W6 i close(sockfd)
/ p9 y, W- v' P1 x- P( w int shutdown(int sockfd, int how)4 d% p; v1 k, U' E
----------------------------------- [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等) " D9 ]- i" p. Z1 j* R! E1 F5 u
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等3 \" E6 i6 [1 z9 k5 y
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
, v8 {4 R3 p; c: W2 M! `- q" \<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等3 ~5 @" E# g+ F, }4 L0 A2 ?
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等4 W3 p, n0 s6 s, N1 `: W" Z
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
( F$ [1 B, Q8 U$ h<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件+ U$ q# b; I: B! l
% w& H/ z* V( q5 a' A
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
) o$ ?6 |' d' [6 n9 B1 |#include <sys/types.h> . t# D0 J- [- ?, M5 @/ k
4 D2 @9 Q9 J5 V, I% c8 T) g
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons7 O; F* o2 `0 W: o/ x/ c
#include <poll.h> //poll,pollfd
! ?3 @( R, J- N- z8 [/ O, n; ]+ ~#include <arpa/inet.h> //inet_addr,inet_aton1 Q/ E& ]7 s- I0 n5 I1 ^# A
#include <unistd.h> //read,write
& K: t C6 [6 t) t#include <netdb.h> //gethostbyname
3 w& C/ F1 M! t0 g5 j* i1 U" p+ Y- a
#include <error.h> //perror! A" `) L& }' h [, B6 `8 O2 i
#include <stdio.h>
* ]0 U5 i- H" e+ G m) u) }5 n#include <errno.h> //errno
8 b9 D8 |. V+ v1 H% H4 A
2 s! O' l9 y! F' \- i( M#include <string.h> // memset
' j; p' A& v, v3 n0 N4 Z#include <string>
2 D: J. h, z+ T( T0 v#include <iostream>
% J; @, Z0 z7 W! X1 \7 q
4 T* V6 _+ h" F |