[size=13.3333px]一 三种类型的套接字:# T' ~/ C9 @) m( O
1.流式套接字(SOCKET_STREAM)6 u" f1 E8 @: @4 t. I
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。6 }+ a+ h5 i% A
2.数据报式套接字(SOCKET_DGRAM)
7 E+ P3 }0 r2 S& E% G7 c. i+ c7 a 提供无连接的数据传输服务,不保证可靠性。; {% `+ R A' Z% I: r
3.原始式套接字(SOCKET_RAW)+ F9 Y, k, l5 I. G8 ~6 T1 a6 V7 e: u/ G
该接口允许对较低层次协议,如IP,ICMP直接访问。9 \% N+ B- u; t- b8 W" N/ l/ m4 {6 W
$ U' d o: F# I: E# D: p; `
二 基本套接字系统调有有如下一些:( a1 M" z1 D! h1 f' I2 G
创建套接字: socket()
v# T7 @5 z& E6 U! O1 R8 F# S 绑定本机端口: bind()" G' C" i1 i. t5 ^
建立连接: connect(),accept()
y8 Z* {% h9 V6 S, K4 |* V 侦听端口: listen()' H1 A% g. m5 s ~: Z0 r
数据传输: send(), recv()
- ~( E( U1 Z5 S$ [+ I8 G+ }; } 输入/输出多路复用: select()& `( e- ?2 r, J0 [
关闭套接只: closesocket()0 s! M* G. w. `1 p4 Q6 E" ?2 |: |. o
4 u" l+ p- A! m A三 数据类型9 {6 q H. e" r2 i& c6 B" k
struct sockaddr4 I. o+ X% G: I3 c
{
7 G; d, }* q6 S7 s# B unsigned short sa_family; //地址族, 一般为AF_INET
+ l+ g' W3 N' C$ J- @ char sa_data[14]; //14字节的协议地址: L8 y; l- W* _. U6 S8 g4 V
}
: t+ d0 A- |2 B" b* L
, U `8 a6 N# u' U' b7 q5 ~ struct sockaddr_in/ }0 ^5 I, X0 f0 s8 j* m
{" @) M* e( \% R% c0 T
short int sin_family; //地址族+ _, P# w& c& G* {! h
unsigned short int sin_port; //端口号
6 c7 G- C# a9 N o5 {* P struct in_addr in_addr; //ip地址
- o4 P" N# b9 T/ w/ O3 W unsigned char sin_zero[8]; //填充
( v) C* E$ v+ m5 d8 u* | }& @' }' n' N8 Q! P M7 v- @# _
! b9 H) G: C0 A, L& |* b4 ^四 常用函数
5 x$ X- K7 \. o0 S, M9 V$ d+ l 1 socket() q! K; A2 S/ k' K6 \6 S: m% b+ U" h" x
头文件:
1 y9 y4 q6 a+ G #include <sys/types.h>
, C8 @0 x& j3 [! p+ q) b/ B #include <sys/socket.h>$ {/ B) p# T7 l! N' O2 i0 Q7 t
函数原型:
0 l& A) @$ @3 g( y, i int socket(int domain, int type, int protocol)! E% Q) o: f" P' J% e
domain: 协议类型,一般为AF_INET
8 E3 x; Q7 |2 j4 ~5 y8 Y4 X type: socket类型" |" k: Q# X' B
protocol:用来指定socket所使用的传输协议编号,通常设为0即可
' K6 x8 t, m; R9 {8 C
* Q5 F: T3 P# K7 w2 p b; C 2 bind()
( ^7 r; D5 E8 d7 j2 g* w- n 头文件:! Q2 r5 @! v0 u
#include <sys/types.h>2 h9 _0 i9 @& ^) Z* k% S0 ^, m
#include <sys/socket.h>- ]6 a) z6 n+ v5 a8 f
函数原型:2 Z5 Q6 e" K+ N, h$ _
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
" }6 z2 @' d, M+ B7 k, Q/ i$ ~ sockfd: socket描述符
) \% e( {; a) P7 r- h my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
+ h3 M! I" v1 Q3 M' I+ A addrlen:常被设为sizeof(struct sockaddr)& y# q/ q" L$ @1 B' E5 a! V
% ?% T7 I4 m4 j, @
3 connect()
0 b3 Y2 f; A4 h; o( B9 w+ g: C 头文件:/ ?+ Q; S! t: z& H9 G
#include <sys/types.h>
B3 O2 k' v! [2 A$ h; [& S #include <sys/socket.h>. `# p( Y" ~* s# W3 u! c4 m$ ]
函数原型:
3 _2 K2 K/ g: x( p" @ int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
$ m* I8 B# \7 c# p# ^2 x j& r! L+ Q sockfd: 目的服务器的socket描述符5 t; V6 k. s4 I
serv_addr:包含目的机器ip地址和端口号的指针
7 C7 b3 n& q V% [: v& K4 K addrlen:sizeof(struct sockaddr)
( B9 E" y2 C6 ~# B( |6 c+ |- ?$ t$ t2 A, M2 E; r3 Y# P$ r1 |
4 listen()4 k0 V/ u" u8 U2 T$ s$ ~0 O$ x
头文件:5 ]5 x* i. h. R' ^
#include <sys/socket.h>8 ^5 n7 \& ?( t
函数原型:4 a# g% K! P$ s' [2 s+ l: R/ d8 B
int listen(int sockfd, int backlog);
s Z% S9 f; \- o+ B sockfd:socket()系统调用返回的socket描述符
9 }0 ?, |8 _2 X backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。4 G% e2 S6 e; j! _
9 {) D4 d( m1 @$ @& r+ q& H3 N
5 accept()
( v7 N; m' I0 h 头文件: 6 T' g3 x$ l7 @: Q- w& P; m, P
#include <sys/types.h>. A: _1 J) O, w& m/ E
#inlcude <sys/socket.h>
" _! t6 v7 c6 [% S 函数原型:
# B4 C1 y1 |! w8 g% [$ U8 p. { int accept(int sockfd, void *addr, int addrlen)
: [$ t: f& L+ _8 h( k' o' x& C sockfd:是被监听的socket描述符
& E6 L4 \1 K S( C0 _ addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息! W& V. G# H- ^/ `4 k0 B2 R# C: R
addrlen:sizeof(struct sockaddr_in) k6 _) z7 _* w: L
/ ~$ a: ]! d) g7 t$ ?* Y v0 R% i 6 send()
% x9 l! H& J7 _- R( U1 W 头文件:& u# Z2 O. f7 t2 r+ b- o
#include <sys/socket.h>
, E; j9 u4 R* n+ W 函数原型:" I1 q4 m! d# s1 Q7 d
int send(int sockfd, const void *msg, int len, int flags);! d# r. ?8 V+ [/ r
sockfd:用来传输数据的socket描述符
; |3 K5 x1 f. }4 w( I# C msg:要发送数据的指针
4 I/ c+ h% N: T6 l4 ]4 D flags: 0. M. c) e" b' B. y4 d& `2 O2 d
5 M4 y( F# ~1 F; S+ n2 @/ }2 y 7 recv()
h3 t# S- [, ?/ F* i* e 头文件:
+ i. e' T) d" E+ a; z #include <sys/types.h> F: d* ^! s( D! M
#include <sys/socket.h>6 f- f9 @( v6 ^" y
函数原型:$ T1 S6 U/ R% {2 g2 n$ ]) v1 b
int recv(int sockfd, void *buf, int len, unsigned int flags); k8 g. \! u0 d! o9 [
sockfd:接收数据的socket描述符
$ E( v- o# H! f6 p+ c; r; h% k$ a2 F, N buf:存放数据的缓冲区: M* K9 `( \7 G
len:缓冲的长度
0 R' `. x! C. t, N; Y flags:0* C" d% J0 @/ w$ T* Q
f# n, ~: ], K9 J
8 sendto()
9 o$ V, R( p8 } R 头文件:
0 U3 V& J4 G8 b; b1 Z #include <sys/types.h>
% U: N, h: C9 r, R% T# K/ l1 p. [ #include <sys/socket.h># v0 k' `- D' B* z2 a
函数原型:. R5 W3 g4 S |
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);$ C, E+ S6 g0 Z$ _+ `& [
& b7 b$ U$ Q6 c
# s( c/ a) m @ 9 recvfrom()
% s( Z8 B" O+ X( G. ]3 L% s! ]* Q 头文件:. H3 }. H9 G% t! x" \ |
#include <sys/types.h>
3 d* E$ b# }, D: j4 q& x #include <sys/socket.h># M; N# J/ m% `1 {% j
函数原型:
* s* G. x" n K int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)) \, U6 k" U6 _) o0 O: X
0 J( w6 }& I8 V8 m3 J- X* l2 R5 F3 d / L, i4 Y4 O- u9 N0 }$ \* w
10 read() write()
- ]0 a) f1 a) x& c int read(int fd, char *buf, int len)
& E7 M7 v4 B! O5 b' B7 W# q" d int write(int fd, char *buf, int len)* [% g A9 c% Z" y1 H1 k& f
' m& P- g% @7 M' w( j5 ]& Q( b
11 shutdown()
* R& l2 o9 p# R% a! j; `7 i" m close(sockfd)6 j9 [3 v7 g& z- c9 f
int shutdown(int sockfd, int how)7 Z% ?" v' n0 g& F6 j
----------------------------------- [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等) / b Y. K$ Z) g* u- p; u
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
4 P; u+ G( s& @% R9 y* S1 Y<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
5 o: x3 ?7 R) f& ~<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
8 i% G' L D3 w* y' ~% H<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
+ W# e2 C+ Q' y6 s# S<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等 k7 m+ a0 e( b
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件. R+ G- p& m$ U
Y H: {3 L) c: `: k' L% @
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等3 a6 b# D* b3 Q0 K
#include <sys/types.h>
8 z+ v$ V8 s5 @" t1 F6 l% m, ~) q
4 m. }+ `( j) W6 V# Y, B1 _; [! }1 q! }#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
* ~+ { w- C" `5 l#include <poll.h> //poll,pollfd
1 ?6 a9 v% s8 i# t9 e5 v; _; w$ B G#include <arpa/inet.h> //inet_addr,inet_aton! V( y; \7 H* C( N y
#include <unistd.h> //read,write
& P/ q, H8 ^ {3 W! |; B#include <netdb.h> //gethostbyname
) K! D2 J1 G3 H) R9 ?
' o0 e2 |( \$ s' O5 D, P, n#include <error.h> //perror5 `9 \+ ` @0 H
#include <stdio.h>
7 ^* b( a5 B, E9 _/ v X#include <errno.h> //errno
& w. C" E9 V/ Z' ^1 @4 f5 T
3 e% q; J4 B2 A' r: o#include <string.h> // memset/ ?( t! u. N$ L" }2 ^4 \! t! V
#include <string>
! q+ b( z* _* a% s' h#include <iostream>
/ `% J- e, t4 K4 k% }2 \1 U6 y! K% H2 }, i5 B
|