|
[size=13.3333px]一 三种类型的套接字:
$ R4 x& h. X# A) d1.流式套接字(SOCKET_STREAM)
+ O9 D# W# N7 L1 s5 W 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。2 g9 c4 A" P, V- `# q9 v
2.数据报式套接字(SOCKET_DGRAM)9 |# _2 ]; G4 I! U! V& z2 L
提供无连接的数据传输服务,不保证可靠性。" i1 l. z: o2 m9 v% Y5 L
3.原始式套接字(SOCKET_RAW)7 l9 k) a5 |" j0 V0 P" u9 u
该接口允许对较低层次协议,如IP,ICMP直接访问。
0 M5 _8 _5 f2 n! w1 t* X0 |& ?2 o0 d- _9 h* H
二 基本套接字系统调有有如下一些:' j$ G+ ]# L) `3 q
创建套接字: socket()
+ e/ J$ W4 |. X, ^ 绑定本机端口: bind()
) E7 {8 i1 n) Z 建立连接: connect(),accept()
7 T5 f X; D+ l% ]" @ 侦听端口: listen(): E( c/ m- x* K# |2 Z& u
数据传输: send(), recv()
* {& n8 I; E" G9 c- J8 p 输入/输出多路复用: select()+ m* E# j* d- Y1 _/ s* @
关闭套接只: closesocket()5 K3 k/ P/ N8 o7 O! o" F. x
/ o& Z, ?. h$ A! ]三 数据类型1 V; b7 R: j) g7 S
struct sockaddr
; X: ~3 K$ l: c* f" h, z0 ^5 s {5 N+ `* w9 X! E# E6 F/ G
unsigned short sa_family; //地址族, 一般为AF_INET
' R0 a& J H6 F5 w% D char sa_data[14]; //14字节的协议地址
8 y9 W$ y# P/ z' s }- d9 t& [' C3 `; ]
1 _+ s. i7 c* U8 x struct sockaddr_in
5 a: y" K9 L. z- u* O {
( f4 T0 F% ?9 {* O7 c2 v, A. ~ short int sin_family; //地址族7 S; j- O6 p$ i, A) U/ T- p, k3 r( D
unsigned short int sin_port; //端口号$ A# \4 N: B @+ c9 R7 V
struct in_addr in_addr; //ip地址
& j: B: s, ]& C; A" p8 [+ G! I unsigned char sin_zero[8]; //填充* t0 D5 n, E% f
}
1 H7 ?/ b7 R' [9 V% ^6 ?
: `( B& a# ~' C" ]# N, O& v3 `四 常用函数2 Q# h3 j0 W2 N7 x& m( H
1 socket()0 V9 A$ r+ u" h X: v: q! H: J
头文件: ' H8 T ^6 u+ @! e5 W) ]5 O, j
#include <sys/types.h>7 n) N5 h' {/ b4 q9 v
#include <sys/socket.h>
# Z- @5 T, Z+ e6 o 函数原型:
: @2 G7 o$ S4 G& [* U2 W int socket(int domain, int type, int protocol)0 F+ M. l0 J: M Q* E. \% t5 x
domain: 协议类型,一般为AF_INET
8 u% r& u4 b! T) J1 c, ~ type: socket类型* A' E6 K; C- f% Y6 U% h
protocol:用来指定socket所使用的传输协议编号,通常设为0即可; l! Y1 a: Q) r
5 a N$ }: f5 { 2 bind()
6 D7 l- g4 X. n 头文件:9 J" @1 }1 ?2 h% f& C8 z& Y' A& Q
#include <sys/types.h>
9 v1 A+ D7 q) }& m #include <sys/socket.h>9 C* W5 _0 F. y) R; f6 H3 Y
函数原型:5 X, a% ?6 m) |& E; ^& V$ w1 _
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
1 p# d" a+ Y5 f! D sockfd: socket描述符+ c* _9 W9 k0 e8 M
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针, b! w' W. r7 [" H4 h
addrlen:常被设为sizeof(struct sockaddr)7 X/ T1 S" N( v, C
% y( o' B1 J" C5 H8 T, F' W
3 connect()- F$ S0 N( i6 V. j9 [
头文件:
! \6 X6 X, G7 G1 I% f2 P8 \* M #include <sys/types.h>
+ b- q0 S' |% a #include <sys/socket.h>
( X6 b$ u! Z5 z1 d' u. l; g 函数原型:
) E# b; T* g( H7 l0 z int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
- }( Q; N1 ~! G7 @ R sockfd: 目的服务器的socket描述符0 W; X u1 n6 Y. o/ F* m: o w8 D
serv_addr:包含目的机器ip地址和端口号的指针1 d; V# [+ ]9 R: G8 l
addrlen:sizeof(struct sockaddr)4 b: V2 _& D0 [; }* o0 s& R5 S
1 J' U/ B. K E0 v4 L
4 listen() f b. o8 f% ^- T f2 m
头文件:
' U6 _* d& e* Q; J7 F' [, w, p# ` #include <sys/socket.h>
/ B( w. Z% @$ G: u- p 函数原型:
0 J/ |: @ |, A8 N2 ~- ? int listen(int sockfd, int backlog);
) ?: @& T2 _# z sockfd:socket()系统调用返回的socket描述符$ V z9 w6 W6 ~. C* p9 S8 H0 }- b4 o3 U
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。
2 ?$ O- ^4 E- U8 T1 p* w+ D4 r" v; [ R, o) v- }7 c+ W8 `3 P. Q
5 accept()
# e& r* U0 S; ~8 x 头文件: 3 o) `5 |/ {4 i; z: R
#include <sys/types.h>1 b5 b% e6 a' }
#inlcude <sys/socket.h>
8 `& V% j- C' T' u% L! q. W0 R/ ]; a 函数原型:' u- c$ b+ D9 l2 g
int accept(int sockfd, void *addr, int addrlen)
, w; D7 b8 a0 h2 a1 c# M- f sockfd:是被监听的socket描述符
& t( s6 J# N3 ~ addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
$ _3 E! o5 T. w! a% k* I: n" A addrlen:sizeof(struct sockaddr_in)3 W9 K F9 I! K7 K2 t
6 e6 [ ? m" {. U& |. [6 |, W 6 send()
3 n' D3 _. _2 }) h: i/ c 头文件:0 p- y3 `8 }/ [3 q; ]# @
#include <sys/socket.h>- ]& u# a* y' T8 ?
函数原型:
k2 e. X5 _' r; O5 V/ |4 t+ k int send(int sockfd, const void *msg, int len, int flags);6 }8 M9 D# C; p- [
sockfd:用来传输数据的socket描述符) X% ~ r. E- r* O* s) A( d, ?
msg:要发送数据的指针 3 ?( `. A" [* o3 w& c9 {0 E
flags: 0
1 ?& `6 d, R, C2 T% D w( G8 [% \) \: ]
7 recv()
l8 W% f" i6 n; t+ n 头文件:
3 s& y% ]/ Q5 C( x #include <sys/types.h>( s- g, E. K' {7 y! D5 O
#include <sys/socket.h>
, b) {" P4 x: O; M 函数原型:8 P/ V4 W2 B$ p# U V" W
int recv(int sockfd, void *buf, int len, unsigned int flags)
4 x2 [! b8 r* H( V4 L8 K- j sockfd:接收数据的socket描述符 j5 @* k x0 B# B' w. l5 j
buf:存放数据的缓冲区4 G; c7 }5 A2 R
len:缓冲的长度 L" U7 o0 R5 j9 Q6 t! E4 @
flags:0
; {1 k. z; B' v1 |
% P: J0 u/ ^# q$ }8 w/ z 8 sendto()
8 Q: g- u" U5 X+ C+ d8 ^/ s/ m 头文件:
9 t5 a! t) A! N5 Z: G) _4 V f! \ #include <sys/types.h>6 l/ U' h# ?2 C% y
#include <sys/socket.h>* I( e8 G; p8 Z, j) d! D8 G
函数原型:/ ~( A' l2 z1 @$ \" i
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);' U n# E; `5 X% a
4 R) Y G1 T+ l! m6 |5 _
0 e5 p# n8 Y; Y" \
9 recvfrom()
2 K: N) T, m. v: C6 r 头文件:+ d) j0 I# [' V' G: v& u# E: O! \
#include <sys/types.h>1 d' m; T; r: s1 B: \$ K
#include <sys/socket.h>
" k2 p, B; U( U F6 i 函数原型:
0 H; N+ l% \# w# m+ m% F) u int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen). w" ], T# a; F7 O3 k) [
! Y: \, A% f1 p" J7 q4 g ' b+ Q. t$ e: w/ {
10 read() write()
) @3 t7 S9 I1 G; `) [ int read(int fd, char *buf, int len)- N/ S9 _! @ R
int write(int fd, char *buf, int len)
, H! i2 R. z& W. P C5 W 5 S, i j; F# N. J+ `. E# E
11 shutdown()
% f# e2 \5 F) Q close(sockfd)& ^ V r: |3 f$ _
int shutdown(int sockfd, int how)
Q2 X4 Q6 q1 g2 v----------------------------------- [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等) 9 @/ j5 H* s" H7 E) v' g
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
( I. d! X" j6 E7 X1 h! [4 p8 R/ r<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()6 w- u# u3 X+ G2 c
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等5 g3 m( m% A9 K+ K' J5 u
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
; A9 m# ?; v P1 [: @<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等- A' X. r! H" h" \7 k! q' L. A7 J
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件+ e& P! C @& C, W$ f* ~
+ U- L8 p6 ]) B
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等: q" q' x& j/ j# l( d) F* {* ]
#include <sys/types.h>
& {" O: ?) }/ G' _& S% a& [0 b9 E. Z" J* w/ j9 o8 s
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
. s4 I4 ]4 y S, M, {+ |- c#include <poll.h> //poll,pollfd
3 t% P9 B1 a! f#include <arpa/inet.h> //inet_addr,inet_aton
. I2 `( D; U4 G p, F- k( Z#include <unistd.h> //read,write
# P7 S8 ?/ m) h- M7 d6 Y#include <netdb.h> //gethostbyname- Y# r. o4 {" R2 I4 ~; |7 N
, i0 m! F. Q r) ~5 h, N
#include <error.h> //perror7 i4 J d y$ P0 \& W9 B
#include <stdio.h>
# z# z4 J9 G; N! p#include <errno.h> //errno2 [" T+ p: y0 t l, U5 l
% k! q$ e# T/ T* I' h#include <string.h> // memset! a9 v6 q# g$ Y( ]- A0 M$ k
#include <string>6 J4 b2 x+ W ~' V0 F- ^7 g
#include <iostream>7 M$ {" a- M0 T; `. w
9 a. a( i% H0 J2 ?" o' q
|