|
[size=13.3333px]一 三种类型的套接字:1 w: R' t6 X0 P+ c" y/ m/ f
1.流式套接字(SOCKET_STREAM), D. Y( U" k' o8 M' B
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
* o- P+ q4 W6 l2.数据报式套接字(SOCKET_DGRAM)
6 _- ]! w% ?4 C, D7 v 提供无连接的数据传输服务,不保证可靠性。
2 g; U% g3 E6 \- L4 V3.原始式套接字(SOCKET_RAW)" s7 c! B6 Z* }4 `2 s
该接口允许对较低层次协议,如IP,ICMP直接访问。
/ o( K- M5 W p& y5 [1 U" ~' j9 U. R8 W6 y- o0 H5 S- c
二 基本套接字系统调有有如下一些:
0 K6 v8 \5 s* ^! w 创建套接字: socket()
5 U2 n- r5 g# R1 t0 o 绑定本机端口: bind(). I5 H' o' A% f+ n
建立连接: connect(),accept()
t$ B! q. a' K0 _' p 侦听端口: listen()' m: l7 N# z( {4 S
数据传输: send(), recv()
: K: T9 ]; | s% N; q 输入/输出多路复用: select()
+ z* y, n7 ~& n6 h 关闭套接只: closesocket()3 V: F: c8 h0 S! {4 E4 ~
! u+ G* B: t( G* C% \( t9 X4 x: @三 数据类型
/ B1 N* g. o' f struct sockaddr
4 m# C; B" y0 W! K0 h {, B, X, m5 u- }. {' l
unsigned short sa_family; //地址族, 一般为AF_INET* r) p# c. N4 ~7 s9 x6 I
char sa_data[14]; //14字节的协议地址5 g1 x4 g) Q2 w' Q u, a* B
}- Q7 K. s: { X& J2 U
8 M2 J3 @7 I @% ]2 E$ n struct sockaddr_in3 @% U* j: |& Z
{
, }5 y, G" F. r0 P0 Q3 q5 P- p short int sin_family; //地址族+ B- [% t8 V% o5 L8 a$ g9 w$ S
unsigned short int sin_port; //端口号: O b7 i0 \; }! l) Z7 ^- i" ~: S P
struct in_addr in_addr; //ip地址) I6 c- b9 x& s- b6 a
unsigned char sin_zero[8]; //填充* V1 l- c8 y6 q' Q. S1 i0 P
}
0 i/ Q5 p) b. Z) Z0 k- s
7 s1 p p8 `& Q$ T四 常用函数
6 F7 {' U2 O/ B 1 socket()
7 p0 I6 C$ W/ `2 w 头文件:
* F+ e' V' V$ y/ ~9 ^ #include <sys/types.h>
9 z! M- o; D ~3 w4 g #include <sys/socket.h>
. [/ f. G8 b/ d1 i, A' ~- j `. J 函数原型:* T; K% a A# A. z$ t4 \1 _2 V+ ~
int socket(int domain, int type, int protocol)" `( k* Q! \; t k
domain: 协议类型,一般为AF_INET
+ d3 j# q' }' a* ?8 J3 H7 y type: socket类型9 L; v# V' H" g) ]
protocol:用来指定socket所使用的传输协议编号,通常设为0即可
, X$ I* a! \9 o/ H" m$ U
2 h) d8 \1 @+ E! j, O 2 bind()
. Z& J1 y" J0 ?- O1 v) \+ s$ c 头文件:
( K% l; l8 P0 W4 H q3 Q #include <sys/types.h>
1 C! [6 ^" L. Q; |% n# z: R #include <sys/socket.h>' q4 C2 b. k( n( e' _4 F" p' ]2 g
函数原型:
& J5 S) I: f I$ \ p! E: n# Z, S( f3 r1 z int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
2 ]6 H3 J. I) W- w$ o sockfd: socket描述符
# I+ G6 U+ Q5 Z! H6 v4 z my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针1 M" U/ ?" [! w% }4 F3 c) j7 z
addrlen:常被设为sizeof(struct sockaddr)
! h0 ?6 i2 K# K, K+ a) n2 |* P( G% n/ p2 U+ A" c7 I1 s
3 connect()
! L5 J6 B( y- V 头文件:
4 U" f5 H$ `5 ^! O P- l* | #include <sys/types.h> 5 v1 G, K2 H3 _; M* B3 |
#include <sys/socket.h>
6 r+ ?, P7 ]1 T* b 函数原型:# R5 k# D8 V% F
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen), }( i6 \+ G, Z4 z! V# t4 w
sockfd: 目的服务器的socket描述符# P( _0 J& L y1 L
serv_addr:包含目的机器ip地址和端口号的指针! Y( P1 X- B: i3 g* P) p7 R
addrlen:sizeof(struct sockaddr)3 c9 }, B# }8 S* u% Y- H
2 O' a" p1 ^& b
4 listen()
0 P0 `# A5 R7 b( N 头文件:
; U O- ?# R0 y" |! ~5 F #include <sys/socket.h>
8 S& K# `0 B2 {7 `. h3 s- d# a 函数原型:8 G4 ], L7 E( H1 a4 f& \
int listen(int sockfd, int backlog);3 K( x/ `. f* d! q+ r% X* M
sockfd:socket()系统调用返回的socket描述符
3 w8 A( ~/ _+ w8 g" D backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。$ |" ?0 \: E* E6 w2 a
6 {/ G! k+ d& ~2 F2 B6 X# C6 E
5 accept()
, H( l7 \. g5 H# H/ W 头文件:
* B5 d! z4 f0 i) u% [ #include <sys/types.h>
3 r2 |/ {% t: K3 ^/ F' p/ x #inlcude <sys/socket.h>
( |7 y6 ]0 g- f6 ]9 G 函数原型:
, v/ [& u' l) m- w/ a: ]! @ int accept(int sockfd, void *addr, int addrlen)
6 P) Z0 T4 O, J, T sockfd:是被监听的socket描述符
) ?) p2 R, ~4 |% k5 a0 D l: n2 ? addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
5 E$ V3 X$ G k7 F addrlen:sizeof(struct sockaddr_in)
( I. [# N- q# @& s! P% ]6 O 8 k x3 E+ `+ I* U& X. @6 p C
6 send()
. |2 @7 C2 t, t9 z E! o 头文件:) i8 G7 s4 i- D, g5 N! G' q% E
#include <sys/socket.h>
3 v1 H4 X' A' [; a6 S 函数原型:9 I/ q' Z) l: O' w
int send(int sockfd, const void *msg, int len, int flags);
1 h2 L8 m3 w& {5 s" p8 ]( O sockfd:用来传输数据的socket描述符( y9 P. D4 c- R- |$ u% @& b
msg:要发送数据的指针
" l" c9 d9 @3 D5 j& r% I2 [; A flags: 0* r# f; O9 j1 s4 `2 p! C' @
! Q) v3 u2 f: B5 p
7 recv()
/ f2 E( U |( w2 U- h, r v9 f 头文件:
3 v- a! |0 m2 K3 t1 z #include <sys/types.h>
( `) y( [/ l4 C: u& Z9 B #include <sys/socket.h>
4 e. Y+ P c3 X; [. V: h/ f2 G 函数原型:! Y( }0 \1 z. m o
int recv(int sockfd, void *buf, int len, unsigned int flags). m6 {' j }$ E! ^
sockfd:接收数据的socket描述符
! i" ^4 }3 r2 t2 G. y* J buf:存放数据的缓冲区
% b4 `# K. e) b" d9 b! N! Q len:缓冲的长度
' a7 q0 W! z6 j0 U! e flags:03 w* @7 F) u2 C' T/ G% g: m
1 B4 o" b! \) E) } 8 sendto()& e, j7 U! i8 d8 h- S) {6 F
头文件:7 A& m' O* m& W i& y4 o
#include <sys/types.h>
& t& _7 E" Z% P3 E$ n #include <sys/socket.h>
$ G% y4 v% ^( V1 X- a6 `2 w 函数原型:9 \) U2 n+ v5 f1 @! t
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
* O. `, L- b% f 1 a" d0 H: o" C/ v
. W% {' x5 W( ]& Y
9 recvfrom() D2 R( G( A% U4 |8 t+ S
头文件:
3 X' a( q% n, A1 n/ a! I/ ]! a #include <sys/types.h>
6 N' W2 O% U5 P9 B; o! P H. n #include <sys/socket.h>, ?: j# V0 c. P4 ]
函数原型:
+ v. p7 _ q) t" c3 i int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)% p5 M* w4 |% Y4 @2 ?
' @1 b$ V1 f- I, t$ s6 y. W 9 ?6 n$ c+ C3 u F
10 read() write()
7 f7 v! ?" J0 n2 Q$ N int read(int fd, char *buf, int len)4 \1 M4 a! @$ R5 g0 `4 i
int write(int fd, char *buf, int len)6 l$ b5 h: Q! t' ^
* k' ~+ M' `8 n) T# a3 x
11 shutdown()' j) I7 b$ X+ \) g+ ?
close(sockfd)
! D, B. H! L D) @! F5 a) C! e int shutdown(int sockfd, int how)* D; r: C" B/ 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等) * p. J% \. o" W1 X
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等" e; i+ t- v- j& n( q& N% l
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
# Y" [( s4 {- P9 W' ?. u5 q<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等$ ?/ i4 W e4 G9 ~( p: L/ t, S* W7 R9 m
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
8 ]: R8 f; {4 m+ _6 H<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
: `) B- H( t' K4 c4 i<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件" p5 x. r5 L+ I
$ j4 _8 x) |* F0 U, `/ \" J[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
( ^( \8 ~5 @' V5 I* J& {#include <sys/types.h>
5 p7 [1 u6 R! \* b" h6 w5 e9 D
( o. `* g8 S/ H$ _#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
1 [' N$ s) d6 V7 u6 f#include <poll.h> //poll,pollfd
6 l4 W; `& B1 s8 s#include <arpa/inet.h> //inet_addr,inet_aton2 ~' C6 E4 V3 |. B' b+ m9 r* @
#include <unistd.h> //read,write9 v# W T4 K( O! x, M* @
#include <netdb.h> //gethostbyname
! \# G. o5 O; d; |0 L: }& g% J: m# N9 {+ L/ u# f/ b& s
#include <error.h> //perror
3 l r; {, y. b& C#include <stdio.h>
' } c0 I" t5 |- c#include <errno.h> //errno( u4 [+ l* { i; f7 ]7 F/ A- O
) D3 p0 w% ~% u; q& f#include <string.h> // memset
8 D2 z5 _) M; ?6 k% R: [#include <string>8 S( r/ Y2 J1 y+ Z n; E
#include <iostream>
, n3 Z% V$ t3 M( B+ o0 Z# X$ W: V& a
|