|
[size=13.3333px]一 三种类型的套接字:
# w$ u3 s! n( Z1.流式套接字(SOCKET_STREAM)
8 M. r+ \; i! y 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
5 Y5 k) \+ p0 l9 A4 `; `2.数据报式套接字(SOCKET_DGRAM)0 D. L {: L4 E k
提供无连接的数据传输服务,不保证可靠性。- H; Z7 Z9 z( A: e6 q* W: C' C$ o
3.原始式套接字(SOCKET_RAW)
* ^4 I9 L; |, z% L 该接口允许对较低层次协议,如IP,ICMP直接访问。
2 Z2 I" \& p2 u" T7 ^( Z- w
# h7 V, G" I" h! V# Y二 基本套接字系统调有有如下一些:& }8 E8 L' k* ?& G+ I6 r* Z
创建套接字: socket()
u# ^3 @. \ Y* R P$ L8 n' V4 a 绑定本机端口: bind()
! ^; z& [! E1 u( m" d 建立连接: connect(),accept()9 D* _# o% m; ^0 h
侦听端口: listen()3 Q" @) W, Q! Z9 x& {8 } A
数据传输: send(), recv()5 \5 S3 c j& S7 ]' X$ ~! y
输入/输出多路复用: select()6 O7 q3 Z' |9 n n. W
关闭套接只: closesocket()
% Q& C- @; }2 b* U! e / z# z9 ]3 F" c5 s8 {
三 数据类型
% O' n3 X9 W7 d9 ]' c2 b( g/ O, i; ~ struct sockaddr
1 C$ k ?* }9 J$ x. `: ? {3 y8 H+ B4 V' O8 d( |: g: ^; A
unsigned short sa_family; //地址族, 一般为AF_INET7 a% A0 \2 w8 E1 q1 a( R
char sa_data[14]; //14字节的协议地址3 v [2 b+ { A( ^: g
}( s! T) L9 U) t2 [0 m
- _/ [+ p: t4 n1 y struct sockaddr_in& {2 K* \, j6 l/ r
{
* F8 I. k: k7 B2 d* P! E short int sin_family; //地址族
$ F! D0 q: f! ~+ O I& R unsigned short int sin_port; //端口号
7 ]) H# v) d" }- |6 {" j. h struct in_addr in_addr; //ip地址4 k; L) R2 K9 g/ B; {; K# Z
unsigned char sin_zero[8]; //填充) ]- j* \. R$ W& v
}
3 A: d' o* d4 A( o
1 o. P: q4 z- {3 |8 ?四 常用函数# i1 ~& M) w5 n5 E. k
1 socket()
4 Z; n( ~+ J* J9 ~ 头文件: % @ i4 V0 L2 E
#include <sys/types.h>/ X* v+ L- y) t9 G N
#include <sys/socket.h>
0 ~. Q4 N& ^" m& D+ k7 e: s 函数原型:
* _2 Q# J6 B: t; Q% u9 O int socket(int domain, int type, int protocol) w7 D Q; O+ n+ {
domain: 协议类型,一般为AF_INET
. v% c( q& N% [7 c type: socket类型& R* a( L4 ^. N: f2 @" ~/ I
protocol:用来指定socket所使用的传输协议编号,通常设为0即可' a1 o% s6 W( |! Z
' u0 G" ^. d4 w
2 bind()
0 A- @8 K4 E" N5 w% G 头文件:# H! U2 c" Y3 m0 j- w+ V
#include <sys/types.h>
5 B( `) i$ t9 `( f, v/ R0 Z #include <sys/socket.h>
6 A3 p- ~8 X! y8 B4 P, ~ 函数原型:( A7 x; W( Z+ e3 O( w2 P
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
) _6 S: j" p% F4 ~6 d: m1 c- Q" ^ sockfd: socket描述符
' U$ U# V4 ^3 q' {: d' t1 {! k my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
2 d' z) t4 [' I addrlen:常被设为sizeof(struct sockaddr)
& d0 f" j, A! m0 z3 p! |. K8 {
6 R' o6 }& p6 n2 n( y3 `) k 3 connect()
( x$ B! S6 v8 q4 m" X) i1 H$ I. T 头文件:
" M0 O- v$ u) Y2 X #include <sys/types.h>
O/ k" r3 O! N B }5 { M #include <sys/socket.h>! V2 k) \: l. h
函数原型:
' W; Q5 K. N0 i" D$ M int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)$ j6 t; U# L$ h8 h8 c* l, H
sockfd: 目的服务器的socket描述符# ^/ @' {' K' j
serv_addr:包含目的机器ip地址和端口号的指针* R: ]' s+ [) [3 w. k3 m
addrlen:sizeof(struct sockaddr)
7 i" W/ ]2 c) [7 {2 {
" K/ {2 s) F. c7 \% [8 X! W 4 listen()
4 u! T/ V/ H9 [$ `9 c7 v) P 头文件:
, a6 e9 A; `4 o6 _ #include <sys/socket.h>
& R) e" o8 i0 \4 \1 g+ |. V9 R 函数原型:
) Z ^% X) @7 i& X9 j int listen(int sockfd, int backlog);
5 D7 ^/ A8 F3 {3 v. Q. N. o sockfd:socket()系统调用返回的socket描述符; `0 j9 `. P4 @7 I# P
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。
# w* J% H3 r6 y9 p/ N! r; V. {9 ?
5 accept()# H2 v. q/ U. T7 @, z
头文件:
6 ?2 N5 R0 X9 @5 w0 Y. ?/ c #include <sys/types.h>- Q/ r' q; z8 c) ~
#inlcude <sys/socket.h>
% I% Z' ]9 K1 ^9 X+ E& N 函数原型:* U$ t$ n! d a, ?
int accept(int sockfd, void *addr, int addrlen)- s9 ]8 D ^% b. T; h
sockfd:是被监听的socket描述符
3 `2 m$ ]) @2 V# p8 j7 ] addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
/ {% I6 \% a: M% E B" j; m addrlen:sizeof(struct sockaddr_in)" V8 G4 {2 Y$ V/ |) [. d9 A, U0 x
o3 Y0 C+ v3 ? V5 N 6 send()
& H* P9 l/ k6 c% b/ w 头文件:3 b& _9 \$ r# u+ D! D0 v
#include <sys/socket.h>2 b8 u3 c! n" K% n4 |* z% A
函数原型:. p" a% y2 z. ^5 Q! J5 m: ?! U1 P* `
int send(int sockfd, const void *msg, int len, int flags);
/ U. k, g+ D! Q$ C sockfd:用来传输数据的socket描述符
# a% X& h+ U! n5 k( n9 F& E/ c msg:要发送数据的指针 - K/ g) B3 L4 I# B& D5 W; P$ B Q7 f& a
flags: 0
+ b' s! y4 G& {( w
& }4 g% q* I" R# R2 e; A) W 7 recv()
$ J6 v [) h) f5 E2 G$ K- k0 n 头文件:
. E" H2 |# B) |, q2 F #include <sys/types.h>
$ V! N, v5 J- z$ R #include <sys/socket.h>
" S" w9 @) ]9 S' l# I u 函数原型:. J+ k. i9 F: r% D O+ M) d6 A2 ~
int recv(int sockfd, void *buf, int len, unsigned int flags)! _- N( Y) b& k$ F1 r
sockfd:接收数据的socket描述符
2 ?1 B4 N, q1 d4 X2 S buf:存放数据的缓冲区
7 Y# b! Q! y+ @: i len:缓冲的长度4 U) n* D! d8 l7 W8 `: q6 T; w( c, B
flags:08 Q, d" g/ o8 A* h6 b( e0 t
* e0 ?& k' }. _; w; {# N
8 sendto()* x& R8 }% [, D( W. S, E u' m
头文件:: b2 u6 q4 u; h: H5 s
#include <sys/types.h>! k1 h' n, M6 O
#include <sys/socket.h>, s! K& z5 t X3 N* t0 g
函数原型:8 r/ i; ?) H2 K2 b, R
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);- V: v. v' y0 @, \" E2 D+ }
& c' d, b6 F0 \3 @3 \, P
, L3 M+ q. w6 f: W$ u/ C
9 recvfrom()6 w' N- z6 p6 U9 G
头文件:
3 X% K3 p7 ^3 }1 v4 U, W1 i #include <sys/types.h>
" P& w9 U( Y) o; ? #include <sys/socket.h>8 S; p# c; e' t6 B; |
函数原型:
5 q5 w" S7 C" P7 ^8 g7 P* Y int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen); `2 O7 c5 B( [- G" [% E
9 e" L4 v: i6 O$ N+ Y3 F
2 |5 V; \! L# c- F4 X
10 read() write()
: _7 j, K3 `' Z3 P# Y, R0 ` int read(int fd, char *buf, int len)
$ [* ~. S# ]# X* E- G int write(int fd, char *buf, int len), n T& y& g# o' x5 ^3 p m- M
: A2 e. m6 f/ h
11 shutdown()* }" s1 @6 A8 j/ m
close(sockfd)" b, @; N, B5 p! y
int shutdown(int sockfd, int how)
$ w5 F M# z; s8 f. F+ J7 x----------------------------------- [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等) / B3 w4 s7 D4 f' ^/ N
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等4 R7 x/ B z1 H$ e
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()4 j+ X8 H& \7 \) C1 U q. a
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
' k# N1 ]) J* q$ }<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
' u+ q! E$ W/ O" a& `9 H<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
3 G6 L2 {' q9 c7 V<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件$ i5 m3 ^- P6 ~- L+ T3 f% f, p
! K; X1 u) x5 F; I
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
) v- L: j* V4 S. Y, M5 s% i#include <sys/types.h> 7 d' ^" h+ @0 n! k! s K4 c
7 s% G. V, P& W4 T, Z8 F% O#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons2 F& |) m3 ~7 b
#include <poll.h> //poll,pollfd' ^7 |$ x. `/ t% O1 i2 r1 y% s1 o
#include <arpa/inet.h> //inet_addr,inet_aton6 r% \2 b) W% C3 g4 e
#include <unistd.h> //read,write
9 p3 ?( ?( G, e& N2 T$ b l! Z; f#include <netdb.h> //gethostbyname
+ U+ ~1 \3 z3 s" b- l7 F
' m) D' N \! H3 D& E/ c#include <error.h> //perror: \7 r+ B9 H6 H5 }
#include <stdio.h>
: Y l7 \0 f0 s#include <errno.h> //errno2 s* A1 R+ ~% q" k& e z! A& y9 N
- q; |' E8 F8 D+ B S- j
#include <string.h> // memset
, `* F; r2 ^6 d" j#include <string>
8 {# R. T" D2 {2 h#include <iostream>2 n, i0 t) }9 N6 K
9 [! w9 Y6 l: e- k [7 R+ u t8 v
|