|
[size=13.3333px]一 三种类型的套接字:
" I% b, \& n- M) @# q5 S' t K' L1.流式套接字(SOCKET_STREAM) P. @, P- }7 U
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。# C* u% _; D- D; C
2.数据报式套接字(SOCKET_DGRAM) }" M' Z: ]# c) J& W/ n9 ]7 I
提供无连接的数据传输服务,不保证可靠性。
! u. w; ?. `( a6 P; s% g% O" K- a3.原始式套接字(SOCKET_RAW)
: w& [! G0 R* R( d5 X9 Z 该接口允许对较低层次协议,如IP,ICMP直接访问。
: H; x9 R7 ]' o# ~9 c
" m! y' V; v, p5 j% f6 @5 D i二 基本套接字系统调有有如下一些:
$ I: o D: N" a4 I9 V) ` 创建套接字: socket()
2 c$ d! s n( x 绑定本机端口: bind()
. t% Q. U2 T1 ?/ \3 n 建立连接: connect(),accept()( H. j+ J p8 A5 o6 e' Z( Y& {
侦听端口: listen()
; f8 i& W. K4 { 数据传输: send(), recv()/ }0 D) d) v- x; o5 [8 B: {
输入/输出多路复用: select()9 a; o' c: ?8 p5 F% a
关闭套接只: closesocket(): H1 w. X9 b( a$ R8 O8 J# E* S0 Z( A
# i* Y+ [# {7 u) h. e
三 数据类型
. j4 m+ |: x( S- a& ^ struct sockaddr
, R4 B- W- G! t7 f {
( n5 L3 g) l2 v, l unsigned short sa_family; //地址族, 一般为AF_INET
1 g( G% u Q$ q$ M* H- L( k) p char sa_data[14]; //14字节的协议地址
, d3 Y: Z5 Y9 y/ T: c }
l$ [4 o _8 R7 C! t% Y8 q6 r$ T& D2 H$ n$ B% q8 m4 W+ Y
struct sockaddr_in
! I& `$ M( z- `. [' x {
$ w$ C* _, w; H% Q8 T1 p short int sin_family; //地址族
: G% [/ }0 ^; l1 a$ O unsigned short int sin_port; //端口号) m8 K1 R8 `4 G- l7 Q
struct in_addr in_addr; //ip地址
' H4 ^% T0 F9 ]" U ?7 A unsigned char sin_zero[8]; //填充
1 {* b: _0 p; S! C5 a; w2 H }
. M$ }8 ~. ?6 A# i: G* R7 L8 C2 d" Y6 @4 ?( d. Y
四 常用函数
. `. A3 D2 H+ z, | 1 socket()' `# h% _8 Y! { A2 r0 C/ _# z; z
头文件:
4 W% s; o# b5 Z7 e1 w9 f7 }* s #include <sys/types.h>0 o# H3 I( o$ h+ N. b3 M3 O
#include <sys/socket.h>
; N* d9 Q7 m5 J. o: i8 T' P 函数原型:( d: I8 c/ Y- E* {
int socket(int domain, int type, int protocol)% W [ \+ {2 e* v! ~ M* O7 r; ^, E# \
domain: 协议类型,一般为AF_INET
. V1 v8 S. v V6 `$ e5 ?; v type: socket类型
/ b# |% J; N. M' A9 Z protocol:用来指定socket所使用的传输协议编号,通常设为0即可2 o% ?# U9 y# P1 W4 h& }. h1 R
' k6 ~& P! d9 l* h
2 bind(). B; q1 d& u5 X6 k" V8 @
头文件:6 v7 ~; v/ e9 H( B; i/ x) z. f7 N
#include <sys/types.h>8 k4 Z5 a& D( ]/ y! ^* O8 @! Q
#include <sys/socket.h>, X$ V) A8 w- {$ M7 f G
函数原型:
7 h: X, O; Y- v0 `4 q) ^ int bind(int sockfd, struct sockaddr *my_addr, int addrlen)4 ]' A' e' \4 f7 k3 {
sockfd: socket描述符+ G- Z" U8 W, I
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针 @6 p+ k6 z; d- \) D9 S) }
addrlen:常被设为sizeof(struct sockaddr)1 ?2 l4 U1 W0 j6 W# d
6 \: j: T: L7 K+ _+ g e 3 connect()2 O+ h" B r1 \) E
头文件:
A3 X7 `, @" s #include <sys/types.h>
) y2 L4 N# W1 m2 o) ` #include <sys/socket.h>
6 u8 ~1 b3 V6 i 函数原型: q9 _/ d# k& u3 {5 R
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
8 d2 O& O$ Q1 Q/ ~' Z sockfd: 目的服务器的socket描述符5 Y5 d: ]3 `$ D( H( R- E- Y ]
serv_addr:包含目的机器ip地址和端口号的指针
; m# K0 ^( d5 A, X9 i6 x addrlen:sizeof(struct sockaddr)9 k1 ~, h6 {" z. i
) x* s. I. z! O1 b" |1 i" s1 y* w
4 listen()/ E: X% _' G& P& p
头文件:
$ l2 o6 `8 k3 }2 [ h8 Q. ^ #include <sys/socket.h>! L% `4 H" z; [2 j/ a+ n4 z
函数原型:2 Y# Y3 d, C3 @
int listen(int sockfd, int backlog);
9 d6 x1 `8 \. t. [0 w% N. k sockfd:socket()系统调用返回的socket描述符/ Q# F! ]7 _2 \' x7 G
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。' T7 `6 P/ Y( C* f9 `. J- T& A
# ^; {' z. R: Q/ {1 C: \
5 accept()$ Z5 W% H2 i( x* [3 Y
头文件: / H9 z1 e) O0 K3 Z. E: Z
#include <sys/types.h>
}1 Z1 F+ d) M8 j #inlcude <sys/socket.h>+ D$ x# ?, N3 H6 M" L
函数原型:' G. p" ?- Z3 q6 a2 b
int accept(int sockfd, void *addr, int addrlen) y# K0 @5 c/ |
sockfd:是被监听的socket描述符
6 ~3 o2 {0 @( U% w: `; w! t addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息# g3 g( _3 l; e6 ?4 u
addrlen:sizeof(struct sockaddr_in), \0 f8 T, g* w8 P9 Q, A L
/ e9 f9 E7 [0 w& P, N2 R1 z9 L% F- R 6 send()
) n8 i4 r# \, h8 {" y# h9 v& |, Z 头文件:
T- f. w* V8 [& g5 w Z Y #include <sys/socket.h>7 {) C& l& H+ Z1 x
函数原型:
& x' z" u2 n1 S* x9 T6 @ int send(int sockfd, const void *msg, int len, int flags);
$ f3 M$ b! d# g/ }+ z( T sockfd:用来传输数据的socket描述符
0 K: K: z2 q( T) C3 \' }6 A; h msg:要发送数据的指针 @' B% ~9 L- F
flags: 00 b# x9 i' i h& ^# h
+ l5 ~- X; M+ q2 C& i 7 recv()
: P1 ?/ S7 I! w; B; q% b# I 头文件:6 I* Q! Y! `& {+ e: s ]6 K5 \
#include <sys/types.h>
# x5 x% _1 t+ U- n9 W% ^# c #include <sys/socket.h>$ L! T/ ?- Y1 K' `! ~# Y
函数原型:
8 e$ K3 P# U! D4 x int recv(int sockfd, void *buf, int len, unsigned int flags)
, G% y9 I3 \6 r, i! i" u sockfd:接收数据的socket描述符$ ^; u. ~# L e9 |. |/ c k
buf:存放数据的缓冲区
1 K4 a0 Z" {. V3 v$ M( { len:缓冲的长度
$ e; r' _. i" P+ E8 e. j flags:0& K- S j4 i( F! K) i; f* j5 h
9 K: ?6 C3 \2 E. S5 k3 P 8 sendto()
! d8 z0 V/ V# w( F: t 头文件:! |6 a+ [5 ~! ~ O G. D
#include <sys/types.h>! V( w" u. ?3 j d2 |) R
#include <sys/socket.h>
' J- e D$ e; E 函数原型:
' f p- D9 ?, q, M. f$ c int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);" [- H6 u" _' Y" X# N# t
! }& b9 }2 ~. X( p6 J# a( t
6 \! f; W( Z& a9 E' h o, T. X 9 recvfrom()4 V+ n% a- ]. o2 `- a0 ~
头文件:- k7 x1 [% @8 ]# k% G
#include <sys/types.h>' N4 p9 U2 U/ r
#include <sys/socket.h>
$ c8 b9 D) i* _, p 函数原型:
1 G) `' O$ u: S# L int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)9 a) q" L. S* ^! ?2 |% ?& U5 x( p
) V$ O, }' N& Z- m1 s 6 `9 P, _0 i3 R% l" T( B
10 read() write()( X4 M% T7 M& B1 B, j2 g B
int read(int fd, char *buf, int len)! @: K6 D* ]* j- ?" j5 u" N
int write(int fd, char *buf, int len)- W% |! R. }8 l" s- v
* V7 h7 y9 p7 q# r k 11 shutdown()
( o4 S4 E# `4 j# B$ H% s close(sockfd)
1 u0 x7 {7 m3 M, G" r int shutdown(int sockfd, int how)4 y9 e+ v; Y7 {' Q. |3 g- r
----------------------------------- [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等)
" _' u) K$ p" p' N<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等- ]( @; l4 X4 |5 M" a5 o6 o2 Q
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()1 s' c/ f5 a- _6 v+ b; @& S0 Z* g
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等% y' F7 m% _# W
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
: b7 y$ i: l$ L* N) p& T<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
& J' u( l q" Y3 P! m. y<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件
; ]0 |, T4 k$ M* z! n
$ j; Q! D6 v0 a! N2 e, X+ |[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等) p& G# A$ j7 s$ X0 D, _; _: D
#include <sys/types.h> ! O" R& ] M3 @* e: l% n/ p
3 d0 l* ~5 p. ]. o6 ?#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
) v% w( L+ }& C2 g#include <poll.h> //poll,pollfd- x3 V4 c1 Z, l3 V. B, p) L4 e
#include <arpa/inet.h> //inet_addr,inet_aton6 |5 O* N. l: k+ w8 p7 Y3 H" e5 p& F
#include <unistd.h> //read,write% i% \, T% Z% p0 t2 E! f) F- M
#include <netdb.h> //gethostbyname" X, j" v4 q4 R7 ~' ?4 l' p
9 J1 a0 T U h" ]+ Q9 A7 Y#include <error.h> //perror" a9 H, W: }0 M. B S, l
#include <stdio.h> `" X- j! F+ |, e; R
#include <errno.h> //errno [+ I1 }6 \, E! q
# E5 ^( Q& W# e5 z) j% ]7 C, r
#include <string.h> // memset" K# Z! W* q0 w# R, }' I' h+ R
#include <string>' t4 S. d ^) V. S2 U
#include <iostream>
" Q2 Z( ^% n, X. D$ {& R+ c
/ }" W' |- @ x3 i3 T( V |