[size=13.3333px]一 三种类型的套接字:6 P- e& D0 O- L. M. R2 ~% H* k
1.流式套接字(SOCKET_STREAM)3 m3 M( s/ h$ N1 M5 T
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
6 w4 |! P \" Z S; u6 [8 U' p8 `2.数据报式套接字(SOCKET_DGRAM)" ^+ I9 j7 S/ ?! T
提供无连接的数据传输服务,不保证可靠性。' ?7 D& w2 z) \$ p
3.原始式套接字(SOCKET_RAW)
2 V5 o1 F( v4 g7 H 该接口允许对较低层次协议,如IP,ICMP直接访问。) ], n4 J+ V2 x5 D
9 [# l" D! R! d3 O9 [; T8 f
二 基本套接字系统调有有如下一些:
j+ R \5 G$ `/ b0 C 创建套接字: socket()5 L* i: U7 b, r( ^3 b: `
绑定本机端口: bind()
: R+ M/ }' {8 H+ Q8 T' C! y; L, U 建立连接: connect(),accept()
- U6 L# A2 Z/ c* o, U: A 侦听端口: listen()
8 M; g# _4 ?8 E, i6 [( R 数据传输: send(), recv()
' E- E1 Q) V0 K! R- m& y 输入/输出多路复用: select()8 g+ m6 _( w) n X, T Y& Y9 X4 {
关闭套接只: closesocket()
+ G$ l- Z0 o6 Q+ p, F
5 j& l% l9 i6 `$ H* Y3 {6 c( D6 J" J三 数据类型
7 I/ |3 I) B8 [8 `* O" ~ struct sockaddr2 d4 Y* [1 N; `" R& y. [
{
' w+ C! d/ I6 e( {; g unsigned short sa_family; //地址族, 一般为AF_INET5 g: O r6 ]+ A# n
char sa_data[14]; //14字节的协议地址
& Q% T- |* x6 Q1 g7 O }
; V( L! }# ] G1 f. W0 Y @2 q/ h& v1 s9 b) ~$ c w5 K8 y
struct sockaddr_in7 Q. M& \2 N! [% w6 l& Z! N, f6 v
{
( |1 e# h, H" n4 h8 s short int sin_family; //地址族
* ?! ` J/ g. g2 k unsigned short int sin_port; //端口号: x! B7 V8 F/ Z
struct in_addr in_addr; //ip地址
7 M& M- B- u% P0 P- b unsigned char sin_zero[8]; //填充, x: B2 f# b( Z$ B
}
$ J- I P T' @5 h4 ^2 `$ V% _! q* [. [
四 常用函数
8 ^' L0 d8 K4 z4 l, T! {. z; d 1 socket()
2 \8 l) G9 x8 f 头文件: 1 t8 N7 f3 N6 t8 z/ w
#include <sys/types.h>. I: ]2 W( r+ M) Q5 x
#include <sys/socket.h>
8 K* w7 |8 a( Y ^& H! F; _ 函数原型:+ z8 l+ a' ~* \0 q
int socket(int domain, int type, int protocol)
1 a8 b; Y9 E/ v6 h, \ domain: 协议类型,一般为AF_INET
% C0 V% @8 w; {5 G( b type: socket类型
) k0 i A6 X/ [' I7 M% l1 D protocol:用来指定socket所使用的传输协议编号,通常设为0即可! Y% R J( ^ I+ Z
+ R' A' e. s5 k- E+ q 2 bind()
& _2 s8 k( l e# L; k 头文件:
& `9 }1 g4 a1 R3 V; b b #include <sys/types.h>5 Q* J) c2 e a0 b6 m! L/ p( Y8 f5 I2 F
#include <sys/socket.h>) N- M" w i/ J* R C0 Y
函数原型:" n9 k' r4 n( E3 _7 g7 Y
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
`2 F' I }$ N/ D x7 N/ G sockfd: socket描述符7 a( A) I% X, p: n. L; q, i
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针/ S3 P- \ n* i! u. \% f- E
addrlen:常被设为sizeof(struct sockaddr)4 p1 j( A6 ~7 s7 j* u
8 }& H8 d" A/ C/ ^6 }; t' N 3 connect()
% b e% |/ w; |% k! M 头文件:
% M4 s$ s( a9 G) Q# l, _" ` #include <sys/types.h>
$ Z! }0 Z D' ?0 a, p6 Q6 [ #include <sys/socket.h>
: O; b) u- k4 Z 函数原型:0 F: `% T5 b7 P" J/ q, P0 H0 t
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
3 f) F& l8 Z& `9 ~. m$ J sockfd: 目的服务器的socket描述符. p' h& S J! z! W) A* n' K
serv_addr:包含目的机器ip地址和端口号的指针
8 @$ t' Z& a1 V V i3 p addrlen:sizeof(struct sockaddr)7 f1 a3 G" d) N; R4 s
; T# ]# j& y6 m0 F+ M4 A
4 listen()
0 M. s8 O% B4 }. a 头文件:7 \4 u; p' [ z! J! H, f1 `4 `
#include <sys/socket.h># H# [/ Y. H3 y9 Z
函数原型:- }# Z" ?; Q3 @2 ?2 K D5 v
int listen(int sockfd, int backlog);; u0 r& m4 v- R. \) E
sockfd:socket()系统调用返回的socket描述符
, H$ E4 v2 U2 f( A+ e4 L backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。
5 u2 h; B1 _ f$ W ]6 c6 u* k
) h5 p6 K8 }4 n! H 5 accept()4 @8 G* a4 ^$ o5 d
头文件: ( l; E$ d6 u6 B% f5 w
#include <sys/types.h>
3 Z( U2 @2 k/ y #inlcude <sys/socket.h>
; m; h! {6 X' W 函数原型:
{; t- y: j$ S int accept(int sockfd, void *addr, int addrlen)
0 l) x8 Z1 _& v7 `0 \ sockfd:是被监听的socket描述符9 z. v% C/ T5 D- t6 h; n
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息% `; j/ Q" w& U* P% w$ z7 u; o
addrlen:sizeof(struct sockaddr_in)
6 x" m: k! t# ?+ d8 R, X 0 b7 s* M2 P! n0 s. a I4 x% s
6 send()
0 o/ @3 b# {7 X% M4 E7 Z. ~4 Z 头文件:) U4 k- u# I/ n) B! h C
#include <sys/socket.h>
/ m& F( U/ [( o+ j* p H. W: V0 E 函数原型:* U' C9 H2 E6 @; x
int send(int sockfd, const void *msg, int len, int flags);
" M% Z" R! F6 i+ _ sockfd:用来传输数据的socket描述符; i- s9 j/ D9 \% z) |, j
msg:要发送数据的指针 ; x8 ]8 o1 M: w4 D9 {/ h4 k
flags: 0 j8 s1 I8 w4 p
1 p j) G0 Y! x3 o' K3 r' ~5 a 7 recv()# F7 |' e6 D" }8 ]7 i/ Y
头文件:1 g4 x9 `1 g' e8 j/ L) B0 r
#include <sys/types.h>- R7 A" A1 Z6 U6 P6 b
#include <sys/socket.h>
, ], G1 C" X, x3 l! K2 c7 {( i5 @ 函数原型:
3 {# u& q) M: ?+ W4 [ int recv(int sockfd, void *buf, int len, unsigned int flags)
A- h( j# \" } {8 D sockfd:接收数据的socket描述符
8 A" h7 G7 s6 R buf:存放数据的缓冲区
2 w& @ a2 K$ f4 L7 M- g' U$ B len:缓冲的长度' }. Q: G( d7 H
flags:09 t% H( Y4 Z2 O: X
# z/ y2 B% M. V( k
8 sendto()
% }9 q0 A& n# r* y4 w$ ? 头文件:0 ?" D( N ^4 H5 ? ], J# [: T
#include <sys/types.h>
1 z, B/ V+ l9 I+ s2 M: n: r# j2 q #include <sys/socket.h>$ d5 k" O- s& z1 v/ i
函数原型:
( T' e5 _' c" G. H% H& S int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
9 r: g0 W2 I7 W
7 t; @) A) ~7 O+ Q: ~/ \: v: Y
' Q9 T8 ]: M! q' C5 O+ f9 R 9 recvfrom()* a, v! E$ ]1 W8 d
头文件:: p! o' Z$ P7 [; r3 i& e
#include <sys/types.h>* | o; c0 q/ }
#include <sys/socket.h>+ ~( H. p& M# Z& }2 h
函数原型:
9 l5 [/ K$ Z/ A: x int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen): v/ S7 I9 L: [3 Y& f0 j4 q
7 `" }. X2 @3 c' ?3 j0 N2 {, |
8 }4 l1 k8 X0 S: @ 10 read() write()
, ~, y, C1 `/ v+ [+ b int read(int fd, char *buf, int len)% d8 l" c! Y6 w; c" `8 V
int write(int fd, char *buf, int len)# A. h! k! u! P& ]3 N
) G. U# y' C4 b2 M5 [3 V! h4 D- M 11 shutdown()
& n$ ]. I( m$ G% u! A: G close(sockfd)
+ l4 z( ^( t* }% v7 p3 n* G) V int shutdown(int sockfd, int how)
; K; H+ T4 \' {$ Y( W- B----------------------------------- [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等)
+ ^. v! Q5 ?- f: P- \5 g<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等% H5 {; [; H* R/ g& g' _
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
2 f. Q8 T$ |. X' F2 @<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
9 U4 f9 L# I! l2 R, Z: x9 [+ g<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等. Y, }) z4 S/ q
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
) G0 Q0 u2 P: i H! E( l( @. L s<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件' n g \' r, X4 i' ~7 { L3 [& v
/ {- i7 M/ h3 M1 J
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
2 O( S# r8 L S2 `#include <sys/types.h> " L' R, L! l5 D3 S6 U: M3 `8 [
# V x. c) C, K( g" [" D4 k#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
5 ~# Q* S! O- K2 ^7 V#include <poll.h> //poll,pollfd# B7 A( b3 b7 h7 y
#include <arpa/inet.h> //inet_addr,inet_aton0 I2 q6 O" G' z# r
#include <unistd.h> //read,write
1 X) ?* f' C$ u4 j2 S' ~+ u#include <netdb.h> //gethostbyname
' R$ Y4 g$ x) w u# P3 u5 J( f) Z9 b6 O3 o% J
#include <error.h> //perror* g0 [) K* d3 U4 s9 x
#include <stdio.h>" y9 V, R% B7 p+ Q. O: K
#include <errno.h> //errno
6 Z7 y! ?; Y9 u8 U: P
& d& M/ Z. Z: |8 j. t* k#include <string.h> // memset$ j9 M6 N0 Q) p2 p1 N U
#include <string>; w5 b o7 ~5 M9 }# _
#include <iostream>+ `, j7 B& p: C- \% g
8 N! {9 e$ b' G5 S) f/ S |