|
[size=13.3333px]一 三种类型的套接字:
0 M E5 q. W* o1.流式套接字(SOCKET_STREAM)
, z! V2 f2 ?' a$ x( p; a* G8 f5 } 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
( l2 X$ N( r$ K& \1 G0 q2.数据报式套接字(SOCKET_DGRAM)9 J! b. f( d/ V. q
提供无连接的数据传输服务,不保证可靠性。: L: ^9 I. C3 j9 c7 U" U& ^; Z/ X
3.原始式套接字(SOCKET_RAW)+ A+ M) d* D+ L
该接口允许对较低层次协议,如IP,ICMP直接访问。
3 I ~ c- ~% N* b7 v$ K# ]- P+ h) H
2 i! N ^% z( w5 x! Q" ?: c( H6 k二 基本套接字系统调有有如下一些:7 w2 @0 C+ h7 G- O# e9 S
创建套接字: socket()
( M- B" N% x; s4 Y+ d1 S 绑定本机端口: bind()& Z+ R2 J/ E2 l' V5 `% J* W
建立连接: connect(),accept()" r) i) }! ?* ~- f' P7 I4 h; Z+ \
侦听端口: listen()
/ {& y* P% w2 S) N 数据传输: send(), recv()2 h+ _! p: w* y- X% w6 ^ @
输入/输出多路复用: select()2 k0 q; Q$ S- S+ [/ L$ f5 M X# ?
关闭套接只: closesocket()
) Z6 ]. y. y2 [6 K: H 6 U4 ~8 W- p5 e/ L1 F+ u5 ~
三 数据类型$ X, I: e1 f# e1 x" l6 i. H
struct sockaddr/ `5 ] c- l" f& {; d: ^7 y
{
# j' M1 h6 _1 d0 Z* a- _ unsigned short sa_family; //地址族, 一般为AF_INET
& G: p5 U, P4 o7 ?7 } char sa_data[14]; //14字节的协议地址& C* G& J5 g" c- E% ]1 h# M
}: Q0 p) L, O4 i2 X6 U. _
8 N* |0 T# z: ^. s
struct sockaddr_in
7 I& I3 A P0 x% I0 s {2 T& x( r, `" \6 R
short int sin_family; //地址族
; k& r9 k: t: ~* f+ ^* B# v unsigned short int sin_port; //端口号
q- W6 J4 w) [6 D! E3 X$ ~ struct in_addr in_addr; //ip地址- n- l' x m* ?$ ?3 n: i9 f& O; x
unsigned char sin_zero[8]; //填充0 \0 Y) |1 z; C5 e2 H( q% W* s
}+ z z7 @" ^* Q% c- U
( \, e0 |; O7 l& V% c$ l5 N2 a( r四 常用函数( L8 U5 H# O; y" c1 e- ~ P- I9 r
1 socket()
. C7 X& B2 m5 W6 J6 J P 头文件: - ] c* B$ d8 y+ e% E, S- a; ?
#include <sys/types.h>. G, W' K6 Y1 b9 ?9 |8 K
#include <sys/socket.h>+ v, G% q5 P) m4 v* c
函数原型:8 I8 L6 A s4 z' a4 Q
int socket(int domain, int type, int protocol)& N8 z2 T% d4 v" j- ]8 K
domain: 协议类型,一般为AF_INET! g/ Q& @+ s/ ]0 D* ?: Q. e. }6 [0 ]
type: socket类型3 V3 p( B2 \' [* x
protocol:用来指定socket所使用的传输协议编号,通常设为0即可. h, Y( C) H1 n0 u3 `
6 z( l" c; D+ }1 Y- @ 2 bind()
( `* B' p, m# I; `6 H 头文件:
0 S. M4 b# q: m- I ~* i; [& ] #include <sys/types.h>6 o2 P f; G8 W5 k
#include <sys/socket.h>2 O, s( [( Z) u; ]2 ~/ F; q
函数原型:
7 @1 {# o9 C8 ~7 ~" ^ int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
5 L. s$ R% O& c. T sockfd: socket描述符
8 S5 N$ I9 n: ~; j$ v my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针" D% M* G- q6 L W- K7 a+ B: J
addrlen:常被设为sizeof(struct sockaddr)
1 P# Y( R J" ]; k, B- `. K( b- M$ H% X. U" t# \! e( y* m% A
3 connect()8 c1 T. a u4 b X7 U
头文件:
$ O$ w j! _$ S% Z3 T- e #include <sys/types.h> 3 c9 @7 ^; V* F. g# G# z
#include <sys/socket.h>
- l l! K" p4 \, r% z 函数原型:
. B+ B5 ?! c4 n; T+ R. B+ s int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)$ K% z4 p' p8 S4 X$ V
sockfd: 目的服务器的socket描述符! |. u, m5 J4 Q: r$ |$ S4 }' z& s+ s
serv_addr:包含目的机器ip地址和端口号的指针" F9 E( I x/ U1 H) f( L( S
addrlen:sizeof(struct sockaddr)" R+ `* U+ d$ Z7 q4 u$ T
8 r5 `- f! ]5 V2 x 4 listen()# _9 c6 `: g; g% H n
头文件:
( ^+ l: Z6 V7 y: J) _( m #include <sys/socket.h>
8 Q0 G5 j; d: g/ o) t 函数原型:6 Z1 W2 a" g4 L+ k e
int listen(int sockfd, int backlog);
1 F0 y- E6 ?9 D/ l& m5 ` sockfd:socket()系统调用返回的socket描述符! A7 E2 K' P: D4 A' W) J" I
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。
. K7 O$ U+ S% l. W1 Y+ L
5 v- J& m4 {4 M e! r: \) Q( f 5 accept()$ n. y/ L$ j3 p- W, a+ {
头文件: 9 v% }" N; M+ P
#include <sys/types.h>
' e, G5 \& a" N! |$ _9 f" l2 ~ #inlcude <sys/socket.h>
) z: R0 o$ `# w 函数原型:" K4 ^7 c. E7 n! A0 ]9 {
int accept(int sockfd, void *addr, int addrlen)3 H( ~5 i7 S. H
sockfd:是被监听的socket描述符
3 J% T0 C8 q$ C addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
/ k, G0 a6 U( i' \9 P- l addrlen:sizeof(struct sockaddr_in)
& W8 v* I0 u( Q5 G
: J T; Z/ M& [2 A# M 6 send(): K) G+ B! B/ s o! K0 m( f1 ^
头文件:
/ K) ~% u, B4 ^1 `' ]5 ? #include <sys/socket.h>
* Z( N7 R6 k+ F" }- ^9 B' B 函数原型:* t/ A& m: E' D3 @1 K
int send(int sockfd, const void *msg, int len, int flags);
1 D3 L9 D2 h% H' z8 O* K& y sockfd:用来传输数据的socket描述符5 Y1 i6 \+ x# b( q
msg:要发送数据的指针 S' n. D5 N1 @2 `9 ]3 B
flags: 0. y- F8 q7 a5 r" v A% {
7 `: R N. N. u: y1 w3 L
7 recv()
' z" I8 _7 W* A9 e 头文件:& K- A% n" n; w3 X- k. Q
#include <sys/types.h>
: K. f5 k% U6 n9 n& _- i #include <sys/socket.h>9 Q# f& U7 f0 W/ P' i6 E! a
函数原型:
7 w2 }- Y! F9 m0 K- f. ~9 c int recv(int sockfd, void *buf, int len, unsigned int flags)! ?& _ k! y* C$ R E6 N; o, A! h" @
sockfd:接收数据的socket描述符* T" F* y- [5 C8 C+ f
buf:存放数据的缓冲区9 q% X/ |+ y: Z4 I) ~
len:缓冲的长度
( L! \ }/ S3 z* y6 @ flags:0
( R! n. c! H. j i( B
4 r+ ^, i& f9 z/ I. O 8 sendto()
. t+ k0 l" W6 P# J6 D 头文件:, D$ Q& |/ A, m5 F6 i
#include <sys/types.h>
' z7 B7 h! S" Y& r #include <sys/socket.h>
8 o: x0 _, v- K' G/ \1 g, C0 Y 函数原型:! k! F: b2 @$ j
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
) ~. X: ] r0 V: \+ q2 T9 S2 i3 j
8 A, c: @( j5 G
3 K& n# @2 i3 H$ C! M 9 recvfrom()
' I$ {* [5 r# `5 G+ k1 e7 { 头文件:
" Y x* Q, [0 g9 E f #include <sys/types.h>
: @/ X, E" q3 C# F7 b$ i$ } #include <sys/socket.h>, X& j5 j- u! y% P1 z
函数原型:; c- V. E e. z
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)% E* N0 s: l7 h
6 U0 u# k# P4 `! Z) u8 ]5 t" F
# }, I4 h9 {8 ~ P& a: A 10 read() write()/ p8 L! A) z9 j: }( H9 E+ G2 j
int read(int fd, char *buf, int len)4 S7 X3 `1 D$ N3 Z6 ^
int write(int fd, char *buf, int len). c W$ q f5 W, Q/ k
- J/ Y5 }! K) W) t$ M2 s
11 shutdown()
6 S9 G+ }" x7 H( p close(sockfd)0 I% t* d& p8 [7 d
int shutdown(int sockfd, int how)- o0 ~0 q1 H8 U/ O
----------------------------------- [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等)
2 Y+ B C# u. [+ r+ S3 D* M<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等8 r* T0 ]" h; T( z8 h
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()+ d8 G3 k& e% o9 l* |
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
& h1 K4 E, e! d; c: _% Q<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等% D' ]" G1 T. L" u. U4 `
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等- m& i4 d N" P/ c- _4 p7 V
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件
w1 C' c7 n7 l
0 |8 @( W* p+ _5 Z6 S* H" G[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
* a: B8 c$ D. ^- b% {#include <sys/types.h>
/ p( Y( \: P- q5 m- X
9 O9 X" Q0 N* J6 E) X' w#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons7 ?" ?: A& k2 S* R( J# X9 |- P
#include <poll.h> //poll,pollfd
/ J. k' G0 \- x1 W" @6 u#include <arpa/inet.h> //inet_addr,inet_aton
$ {) E- u) n @. y+ w4 Q0 w#include <unistd.h> //read,write0 ~8 |+ q: x3 \5 N, w1 @1 b7 J: k
#include <netdb.h> //gethostbyname; b& k! j$ c8 `. v9 I8 b m
: z6 i, [2 S6 D3 O* i9 T" ?
#include <error.h> //perror
8 E* q k; k) s& o#include <stdio.h>
i- T* y0 ?& k#include <errno.h> //errno
# j6 d) ~$ s( k1 s) V# d+ V9 G" R3 H) v2 ]. j8 f) d; i
#include <string.h> // memset
# W6 U- t2 k e5 H6 r3 x1 l- {#include <string>
8 m/ h9 a9 T3 k/ {; l: Q) }9 l#include <iostream>% M0 T- N4 ?8 I; \4 o3 f) Y
1 j* M7 v, I* H' [ |