|
[size=13.3333px]一 三种类型的套接字:
5 f( a+ M: k1 a3 X; S6 Z6 [: n1.流式套接字(SOCKET_STREAM)& v: i; \0 v, ^0 ~* b
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
5 k9 K$ A% p |( h/ W, U3 k; T2.数据报式套接字(SOCKET_DGRAM)! K( v3 B$ s+ |$ y0 N! {
提供无连接的数据传输服务,不保证可靠性。. T: D% D' p+ Q3 f; l0 M9 H
3.原始式套接字(SOCKET_RAW)2 X8 H& p) o% H6 a- `
该接口允许对较低层次协议,如IP,ICMP直接访问。
0 |6 _2 l: ]2 o) q4 S6 l1 ]. J5 ~1 b) R, A8 M
二 基本套接字系统调有有如下一些:
! r0 j% o. F: Z' T 创建套接字: socket(). d& {9 }: L# a, c4 W' d; g9 e
绑定本机端口: bind()
& ]: L1 j1 s$ R# V$ v5 w 建立连接: connect(),accept()8 o, m' F1 x5 t7 c; d/ h) v
侦听端口: listen()
Y* Q6 ^. H' }% ] 数据传输: send(), recv()
) i8 i5 c3 ?, F% E 输入/输出多路复用: select()& u$ b, H. ?7 M1 k! t# I( A
关闭套接只: closesocket()
: j) q+ x) j* q) T9 ^/ x. _2 @; e- G 4 w: r& q& u. c; _/ z
三 数据类型
' X- \. ]) W* s struct sockaddr
! B Q0 L) T3 r {; K7 U4 W' Q1 s5 q% i
unsigned short sa_family; //地址族, 一般为AF_INET/ U- O C5 w3 T1 v- _
char sa_data[14]; //14字节的协议地址; C) _1 x* I( L3 U
}
9 C( }1 B( w1 m5 f# s% n5 s: i4 d# ?% v6 O& I
struct sockaddr_in
5 c3 S; V- N& u/ G# Y/ D" [ e* { {
) [; ^4 d V2 y( Z! R2 f short int sin_family; //地址族
/ x7 J0 M3 m9 W7 m3 D% y unsigned short int sin_port; //端口号 T# B* w0 H* C$ x4 A
struct in_addr in_addr; //ip地址 m6 V' [8 c( U2 V$ E7 z5 Z
unsigned char sin_zero[8]; //填充) D; ?: R8 K! l1 u
}
" `0 o$ Z5 t& V
9 x G" X" r5 R2 h* ^四 常用函数
7 F- o, v( `( P9 z* e7 V# } 1 socket()
$ z9 B: q" e' T! V$ Q* U! ]. P; S; h 头文件:
9 E* A r# z I: B #include <sys/types.h>
- y9 Q6 s b' D9 O$ d3 x #include <sys/socket.h>0 T6 x7 R8 s) b4 g) X* k6 X
函数原型:
9 O' ?# R9 g% _& | int socket(int domain, int type, int protocol)
% z: \! e+ T* m) f9 V3 U5 [! s* X domain: 协议类型,一般为AF_INET
6 R3 @5 d7 S$ s M3 M% h8 ` type: socket类型; q2 |% I- {$ s9 R' a1 O2 a
protocol:用来指定socket所使用的传输协议编号,通常设为0即可
+ e d1 O# o5 {" d- _3 W) h8 u8 F- Q, }1 r/ {5 w: O
2 bind()4 ^ F- F S% ^; L' \
头文件:
: L7 L9 N6 U, p8 ] #include <sys/types.h>
. Y! q( R6 F7 e7 @2 W: H #include <sys/socket.h> C s6 ^9 H% D
函数原型:! o' I/ `9 V T$ p
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)% N7 ~+ o4 Z+ Q- w
sockfd: socket描述符
4 y1 m. f% \* r7 x8 X my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针$ O5 F8 \: w- b; I# u! R
addrlen:常被设为sizeof(struct sockaddr)
: P6 c5 m7 h3 m$ l* k3 t
9 R+ W' t7 Z+ ?" l( X- j8 P 3 connect()! L2 x4 E% o4 f; L) G
头文件:9 y- u R. H$ r. v
#include <sys/types.h> 2 j. @' Y6 y! Z8 H: _* g( B
#include <sys/socket.h>
@) `0 u2 X- v) h7 v 函数原型:
# Q' |. P$ b8 f int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)9 j+ X9 E7 ~9 i8 G) d
sockfd: 目的服务器的socket描述符4 ~- o- P3 g5 v( I* ?
serv_addr:包含目的机器ip地址和端口号的指针
! l! O: W ^. J: h% K( C8 o/ ~$ y addrlen:sizeof(struct sockaddr)" k, J1 C Q7 Z; ?5 M9 X, R
! Y2 g& E9 }- x' Z/ A
4 listen()
: Z2 d! a5 M- H4 u4 v' x2 ?2 M 头文件:9 A& A7 t( i0 q& J
#include <sys/socket.h>. W4 S- q+ i r$ u+ K" c
函数原型:
# E& P; s/ s5 I int listen(int sockfd, int backlog);
' P- T q2 Z6 p' a& X/ F# s/ F) |; S sockfd:socket()系统调用返回的socket描述符
' ]3 A6 }: ?, X' [* B backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。+ B4 V( i2 F B6 |! v" X: g
1 X" U5 o; B' e# S
5 accept()1 O, l2 ]% z( B% o
头文件:
' P% i& G: F& P$ w7 z #include <sys/types.h>
. O1 h$ N4 P' E! g3 Y" f# y- w #inlcude <sys/socket.h>
! U0 Y: h6 G, T8 p/ L+ n5 g5 R 函数原型: ^( I, R2 s2 Q( x" M
int accept(int sockfd, void *addr, int addrlen)
, i6 t; h/ N9 V sockfd:是被监听的socket描述符
* F6 T% R% C c- F addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
7 U4 K5 d; r) ]" N6 {+ g+ ]! \ addrlen:sizeof(struct sockaddr_in)
. g! `: t! B* c
. Q: z- c/ T5 } ]' ~+ Z3 w 6 send()
c, q, |3 M# k" \ d/ ?; e 头文件:( k: d9 b2 m/ v
#include <sys/socket.h>
1 c7 R6 d) P' f 函数原型:
0 Z% Z7 Y- e# A- q7 H$ P% @ int send(int sockfd, const void *msg, int len, int flags);; n- j; v% B, o5 E" l+ L, s% L
sockfd:用来传输数据的socket描述符3 n" q! w) `+ i0 F3 ~9 D
msg:要发送数据的指针 , q# w r8 m2 k; O0 u
flags: 0# _1 E6 o* B4 F6 I( t) i
: }) _4 l( K5 X2 A
7 recv()6 w; v" t, [8 Y2 M X0 b- t3 B
头文件:) ?$ j# d- T6 L0 U5 p0 x" v' v
#include <sys/types.h>
( f- \1 U& Z. |/ ~# C #include <sys/socket.h>7 K- r8 @" ?3 f) U* l6 K0 Y
函数原型:
$ g0 i5 O# ?5 N. B- F int recv(int sockfd, void *buf, int len, unsigned int flags)3 n. H3 H- E; O4 f
sockfd:接收数据的socket描述符* y# I3 K% |! L
buf:存放数据的缓冲区3 T+ I% Q5 y4 M& \) ]
len:缓冲的长度
! g. ]" c" b9 m0 c flags:0/ H5 ?1 z2 Z) _+ |) i ]
* d3 ]1 l% g" l. v 8 sendto()
7 p# \- B+ b% n- u" B8 n 头文件:
2 z0 a( l% k2 W* M: c #include <sys/types.h>; \( O8 y4 d( V$ R, t
#include <sys/socket.h>2 z0 e. R: F" t% I4 X* u
函数原型:
; v7 Q- u4 ~9 F X B3 ~ int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
# q( ?: l s& a5 X
0 g. o& Y; L- r/ W, I6 g: g% \$ V
3 H! c) T4 x2 i/ @# M$ | 9 recvfrom(): C$ Q3 g1 J) q) n1 Q6 d
头文件:9 h) E$ F* ^# K) f$ T4 {* L7 I; T! f
#include <sys/types.h>, B) F; a) x& b0 ?1 W0 o9 `4 k: Q3 G
#include <sys/socket.h>
) M- G, l$ q6 ~. |( I! Z 函数原型:$ u- `! U, c. u- S- @
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)3 r" R/ b* `; d8 y# o6 g4 t( [
. D- f: G$ z: }3 x# T4 D
1 k5 q2 x0 s$ Y- W5 a7 V, h 10 read() write()
! i' X: J$ C* ~( _/ d3 K" o int read(int fd, char *buf, int len)" h8 q% k" G7 Q0 O7 @& d
int write(int fd, char *buf, int len)6 e8 h' ~ H0 m! h1 I* x% S
' }+ g+ L7 [+ v3 l 11 shutdown()
8 a! T. S3 I# }# z close(sockfd)
* E: p1 R3 E" g5 l5 U* ] int shutdown(int sockfd, int how)5 u0 {! H0 g( f n* r9 M* L
----------------------------------- [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等)
) C6 a n8 }( n, I; y1 t# K<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等! g' E ]( ?0 u [
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()( C5 f0 }6 A' D- l
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
9 p I$ e/ T" f: `<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等! k5 ? O1 K/ {1 Q7 b+ X
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等, z) p. L4 q- |" r8 C
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件
3 ^ W5 X: h( g) q6 b! t, ^
! q ^" U* \6 R" l: H2 j[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等5 x: C2 ~; F" A- t/ u) j
#include <sys/types.h>
8 R0 A2 v7 O2 r( B: h6 J( r& R5 B
* l; ~& I1 D: ] E5 H#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
u6 A5 \6 i* e#include <poll.h> //poll,pollfd
- x# E8 [5 s- |) K#include <arpa/inet.h> //inet_addr,inet_aton" k4 P" e5 n, O: }/ B. s# U1 i# q
#include <unistd.h> //read,write6 Z, O) a* t& b
#include <netdb.h> //gethostbyname
+ S2 G! L: K; C& ~2 C2 J5 J4 m& [: L: c# X3 Y
#include <error.h> //perror; T6 U8 ]* K' p. s( h$ |) @
#include <stdio.h>( t: [0 U7 T) y9 C$ J' g4 c
#include <errno.h> //errno6 t F: Z" O) Y R! V
+ ]5 E2 D) u2 B: T5 m& T#include <string.h> // memset
" E" i! V7 x+ e: ]! Y( q7 Y#include <string> o( ?; |! k0 `! @
#include <iostream>
& \! K! d" r- b+ y3 L1 A4 K+ d2 T/ t( T+ m5 L
|