|
[size=13.3333px]一 三种类型的套接字:' `3 Q# B* F; Y% v! V& ?
1.流式套接字(SOCKET_STREAM)& z7 ]8 x4 e. G& J6 l4 A" Q* s
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
- n, P. j( L9 d. R2.数据报式套接字(SOCKET_DGRAM)
/ L' d, Z# L3 _; a( Z( i) j 提供无连接的数据传输服务,不保证可靠性。1 d! K4 q, Q3 f+ N n
3.原始式套接字(SOCKET_RAW)
7 s. H* ]. a4 k6 i 该接口允许对较低层次协议,如IP,ICMP直接访问。
' y* z1 O9 ~& o# B) D
+ ^# p+ ?5 ~3 w; L5 t* E二 基本套接字系统调有有如下一些:
* y- d6 k1 F+ K% `1 l& g 创建套接字: socket()1 }$ e6 O9 l# r; o) c
绑定本机端口: bind()
' T& U/ N: R, B+ K, u7 F1 p( Y 建立连接: connect(),accept()/ {% a/ ]% V7 k5 O! @
侦听端口: listen()
' `3 t( A' {$ a3 c/ E8 |+ J2 h 数据传输: send(), recv()! \" U3 l: o" U8 ]% ]
输入/输出多路复用: select()
4 G7 u3 p6 S% w8 f 关闭套接只: closesocket(): v8 V! B* U9 G0 x$ S& _
6 k3 }" L& K3 N. q( z! A8 j
三 数据类型
2 V1 Q, z' C# K* s! }* W struct sockaddr1 g2 c. R7 t4 ?
{6 M7 [) n, W: M0 t8 }! \
unsigned short sa_family; //地址族, 一般为AF_INET
8 I) b) w P) f: a char sa_data[14]; //14字节的协议地址
& W' Z, q0 } n' L# l' J5 J }
$ Q: M9 z( G9 \) u4 _$ D$ s& W6 `( u
struct sockaddr_in+ F9 Q6 M; y) u
{
4 F/ a# ^: f' ^: r1 ~ short int sin_family; //地址族
( N/ O* s8 r9 j/ j# W+ S unsigned short int sin_port; //端口号
" ]5 J8 h" P$ ^2 l7 c) H' b$ A struct in_addr in_addr; //ip地址
5 L- \: y0 }0 o h( e- \9 X unsigned char sin_zero[8]; //填充' d; w8 x4 g7 J7 v" ]3 J
}
& l- R( }! ]6 u' W4 P4 h
. g3 P& z4 t$ B: g四 常用函数
8 Z' {) J. Q6 c }; S, u* @- v& [; Z% o 1 socket()' k* R1 F- Q; R; d. V' H. a6 _
头文件:
, A" }! x7 X; K/ H! S1 ~5 y #include <sys/types.h>$ |) k5 X+ L. x& l! }0 d; ^
#include <sys/socket.h>. f1 R5 e0 M3 L
函数原型:
, Z8 d& e4 R7 y/ @ int socket(int domain, int type, int protocol): Z2 p2 a T7 z) p0 Q9 \; j0 n
domain: 协议类型,一般为AF_INET! ^/ r4 y! K7 v' l5 i
type: socket类型
, q& A. j6 T+ y. s8 g protocol:用来指定socket所使用的传输协议编号,通常设为0即可/ O$ m4 n% H' c
. @: h4 S6 j* C1 s
2 bind()
3 Z% X" D3 F5 U; s& R 头文件:' O. g( y- m5 B1 m3 I& D
#include <sys/types.h>: L6 U- [* d' l4 ]8 K7 F8 Q: ?
#include <sys/socket.h>
: n7 x' s5 `; o! q# v0 {( F 函数原型:8 a7 i8 F/ y* ]/ c }
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
9 l. c+ I r( r sockfd: socket描述符
, b" U/ a6 J- W! N0 y# ?; L) y my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针1 R4 V7 h) C( S6 x8 J
addrlen:常被设为sizeof(struct sockaddr): |( x' u# A) y1 ] \# l; d) o
' o/ F# y' u$ u$ B" l9 k 3 connect() |( V; _1 q$ G# z; Q
头文件:2 Q5 u0 @" |" j, f- _
#include <sys/types.h> # P8 q% e5 _( n$ v
#include <sys/socket.h>6 C9 X, S& B: p! C9 A
函数原型:
1 a0 v3 b" @5 R# F int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)# r( M1 @5 \4 q3 N h
sockfd: 目的服务器的socket描述符) T% r8 l0 X' E8 x, F8 w
serv_addr:包含目的机器ip地址和端口号的指针+ o; M7 g- k- w; s# H
addrlen:sizeof(struct sockaddr)
! h( X" i3 e/ A, m% c, g. S# l7 i, B/ ?% L: o& M
4 listen()
, }7 W9 D2 ]8 Q 头文件:' `. e( e6 o6 f# a( G+ a# O
#include <sys/socket.h># ]- o+ |0 M$ t$ d1 m* Q5 _4 V
函数原型:
. q* p. Y0 } _) t3 Q int listen(int sockfd, int backlog);
& g, q+ _5 I: Y3 i( [7 `, A1 D sockfd:socket()系统调用返回的socket描述符4 R: @; v. c, G% ]4 P6 a
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。' f, a" S! i, h/ f
. @* r# q* S& Z9 |* z 5 accept()3 c$ P0 a/ Z7 b+ X/ K4 C% C1 x
头文件: " ]5 a3 ^, F _+ t. K+ A* M
#include <sys/types.h>2 r- d+ a* W: x" D. U& x, @ i6 K
#inlcude <sys/socket.h>7 Z! Z( K+ Y6 E+ c* m1 D& K7 p4 Y
函数原型:# w, p$ ]+ Q* y
int accept(int sockfd, void *addr, int addrlen)
- ~; S5 P% n* i; P3 r sockfd:是被监听的socket描述符" I* G, ~ L j& }; z
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息0 }* m- ` B0 v
addrlen:sizeof(struct sockaddr_in)
$ m0 O( K: `( V' y9 c3 @
% F% f) B) I5 u# t/ e0 T* r1 _# y 6 send()$ d9 u: C9 v- ]; K- q# M
头文件:5 Y( T+ o) U3 s6 l+ \7 F9 p
#include <sys/socket.h>8 Q) M" z( G1 Y* H+ t7 C
函数原型:& m* Y- ] { Z4 Z5 u9 }( f4 O6 |) f
int send(int sockfd, const void *msg, int len, int flags);
, y6 u& s7 T# M- r, s sockfd:用来传输数据的socket描述符; E$ `+ J- o4 `: z& ^8 X
msg:要发送数据的指针
8 R9 ~- f; v4 X& C; P$ o; y flags: 0- A% E* S! s) c! |+ n5 S* ^" j
: j* F5 c' ?7 p: Z 7 recv()
5 v. r' z- b& r' H 头文件:* e0 W7 O+ m3 N g2 Z
#include <sys/types.h>2 \" C8 C# |/ K* j+ @' k1 v$ h, V
#include <sys/socket.h> Y+ s3 t! D( |3 w
函数原型:
0 b+ X& V: ~$ P- T6 K8 e int recv(int sockfd, void *buf, int len, unsigned int flags)9 ?5 a1 W& s2 K9 S. N
sockfd:接收数据的socket描述符1 J# o: K# [# c. p
buf:存放数据的缓冲区
/ Y; Q) l, U$ V' z" D len:缓冲的长度
. h" {6 R) V0 |9 o% v# D flags:0" F- s5 a! I8 a4 }
# l2 Z% U" m: c& e 8 sendto()
+ N4 [+ r; i ^+ K: B 头文件:
D# f9 y; z n, b! d$ A0 d #include <sys/types.h>7 n5 w* t6 L% |6 W& U9 F
#include <sys/socket.h>* P( b* g+ {6 x" A g K) P! s3 z' `
函数原型:; T- t1 K, F; \
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);' T! W5 {$ w4 A
* h7 q& p: @# s* a& t
) e, O/ l6 T2 [* O7 l, a
9 recvfrom()* ]1 Q! W* p6 ]; b& @) v
头文件:
/ P! ^$ C! U7 c #include <sys/types.h>
7 I! r% b+ R! o- W #include <sys/socket.h>
. G- i6 Z+ t1 O+ L& [ 函数原型:+ C- d* ^& m8 }6 ^/ c, x2 c
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)
- [# h& v. _" E- ?1 O2 N c# s" d/ M' f' J
/ I4 ]4 e# u2 p- X1 B) E+ l3 r) y 10 read() write()
( ~/ W, s* q7 h x: ^& d% } int read(int fd, char *buf, int len)
! M) ^ g0 P+ R7 H int write(int fd, char *buf, int len)! _5 r" F) z3 A
: X6 l# E; C: U! C& _
11 shutdown()" V$ ^1 w0 R8 k
close(sockfd)
6 @3 X7 x; K# X9 m- M$ J" k int shutdown(int sockfd, int how)
7 o% f# N5 O' V$ ^8 E: h1 f" Y----------------------------------- [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等)
5 l* m- Q) N/ F1 R% E7 W& I& A' [) w<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等 [' |1 a/ w2 O- a% F
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()( E& O i% R& p# b, i O' |
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等/ I0 @: f z4 y& v% m1 \
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
" T* z! S! L- P: Q' n<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等* [& B# ]8 [3 J. @
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件5 U0 C. L P+ D$ a) D0 Q: a
3 q2 I; L0 Y5 N% ^) H! U[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
" F1 Y% v' e" A: F#include <sys/types.h> , i9 p5 r9 e4 W- m- i% X `" L
/ A: x: l# b' _8 u- [
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
4 c# Y' D C3 y* W#include <poll.h> //poll,pollfd5 P. h. ^# [3 d, m* t V4 M4 `
#include <arpa/inet.h> //inet_addr,inet_aton" M) K) `( e& X- @) \$ i) {
#include <unistd.h> //read,write8 W' a7 s4 o3 B2 A) ?: ^8 j! K& b
#include <netdb.h> //gethostbyname" y2 Y+ C: R" O4 |3 H
- ?6 w( m; \5 B0 ?6 B) {
#include <error.h> //perror! ~6 N5 o4 [4 g2 c2 @5 i) c' H' L! E
#include <stdio.h>$ c9 V2 I2 X' L4 z) S
#include <errno.h> //errno
6 {6 \+ j" H$ B3 q( T, u9 k9 H) ~1 Y4 ~* _) g
#include <string.h> // memset
6 T [# r3 E& N( F* y$ P7 C3 k$ n6 U#include <string>: W, w3 r3 \9 _& z) ~1 L* d, }
#include <iostream>
! [/ @0 Y1 `( n* z
9 b7 a4 Z- y9 D7 j' T |