|
[size=13.3333px]一 三种类型的套接字:
9 x5 j, S! |: P, Z$ z$ @3 q" p! \6 F1.流式套接字(SOCKET_STREAM)
+ L1 `4 M q# N 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。& p' ^7 M! C4 P7 t5 S3 f& o$ N* d- U
2.数据报式套接字(SOCKET_DGRAM)
9 c( |6 l+ } u; q 提供无连接的数据传输服务,不保证可靠性。; c" z; S* ?4 q' A1 T3 Q
3.原始式套接字(SOCKET_RAW): ^! h% _& ~* `+ k) M
该接口允许对较低层次协议,如IP,ICMP直接访问。- ?# T& b' q+ q
. i0 ^$ F: W2 K- f2 i5 a1 `4 W% d二 基本套接字系统调有有如下一些:9 W& N* _! U* C5 X3 Q& j
创建套接字: socket()9 r0 A3 B2 j3 `: r8 ?
绑定本机端口: bind()' w- }/ s! v8 k' ]: \. ]
建立连接: connect(),accept()" b% [ |4 i: U3 Y
侦听端口: listen()
9 t' s' u( ~2 x) S& Y2 ^* d3 }! u/ z 数据传输: send(), recv()
b1 u0 o. ~) m$ h# | 输入/输出多路复用: select()1 u4 S+ h- r) q7 Z( T: o, L7 R
关闭套接只: closesocket(): o- X! n3 f, v
, z0 w2 S2 a4 ~' g三 数据类型
- ]7 L' U$ L4 c9 V% | struct sockaddr5 A0 t% V% Q. n
{
# W+ }. N8 N" a- Z3 V5 G/ Z, M unsigned short sa_family; //地址族, 一般为AF_INET
5 G% Y5 e- w, S9 h1 n! L5 } char sa_data[14]; //14字节的协议地址
+ C' l8 z2 D2 n. V& B }4 ]* V4 a3 T7 P7 r+ R* w7 _( I3 e
6 }9 ~ t4 `8 H7 `
struct sockaddr_in
+ \& z) T7 C4 U ` ^ {) A9 u) B: o1 r, a3 T
short int sin_family; //地址族- X5 k: k* {5 ]. u4 a% ^& i
unsigned short int sin_port; //端口号; ?8 d, n( Z; t- P; T
struct in_addr in_addr; //ip地址
' s; @! ~% S; E unsigned char sin_zero[8]; //填充
5 ?0 K. f( B2 T. C }
/ t, s$ Z _; S: b" ~( i+ Z1 e7 [" S% `0 q
四 常用函数
( I$ z. S8 D* [/ t 1 socket()9 r1 y8 \$ @2 V; ?% P2 s0 }
头文件:
0 H; t" s% Y8 i) z9 q1 _$ {% @ #include <sys/types.h>+ M0 y/ ^$ N; a$ `1 u( ~/ z
#include <sys/socket.h>
( u4 w o& x: u3 F; N# R! t! X+ l q 函数原型:% O/ Q* l% s: \$ I
int socket(int domain, int type, int protocol)
8 P% J" T @) ^- c' T+ z& d domain: 协议类型,一般为AF_INET
3 \. |3 t5 i2 ~) O6 T! h$ _6 A0 b p1 T type: socket类型
9 d; I" x5 h+ @5 h9 b5 }, @! q5 e protocol:用来指定socket所使用的传输协议编号,通常设为0即可1 K. i& y) p) Q$ t
8 h1 C q) Q/ H 2 bind()
$ j$ g# C5 V% }8 ] 头文件:/ w3 j j" @- {4 L& Y; I! o
#include <sys/types.h>
# V0 I3 y' L/ V #include <sys/socket.h>, F, K9 y0 ?/ I! k2 h4 \8 K- w
函数原型:
) r1 A$ `/ {6 [3 z0 _5 m4 w int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
4 b" Y: u( K# @2 G9 O, a sockfd: socket描述符' L, R' i8 n. d c
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
, s! E6 Y6 t6 B5 R0 j8 g addrlen:常被设为sizeof(struct sockaddr)
6 n- |; R6 G( J' @( t1 g, J$ [9 H9 W
# H% Y+ `! h( A/ b" z# u3 T& w 3 connect()2 [; ~$ Y$ u' V
头文件:/ e& w- P H3 ~
#include <sys/types.h>
( u; U) v2 ?* _, a6 Z6 w3 { #include <sys/socket.h>. L/ G+ e" z& \" b/ r/ k4 g, V
函数原型:# a& U1 a+ A0 T. l
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
# Y4 F$ r" r+ o, B, H$ w' ? sockfd: 目的服务器的socket描述符
2 z9 p) f. a" m* h1 E serv_addr:包含目的机器ip地址和端口号的指针9 T" N; l. w6 p! x* L
addrlen:sizeof(struct sockaddr)
- i3 k! Q+ x; E! J6 F A7 E+ j4 u4 U$ _9 Y* f2 y& J
4 listen()
/ N% D0 [ [9 c6 g% \& | 头文件:6 E) c) {6 G/ W9 `4 _
#include <sys/socket.h>
; P0 T' t1 F2 |3 d; u3 V 函数原型: D2 ^3 n7 ^5 v7 e9 q4 R t1 b
int listen(int sockfd, int backlog);
1 C, Y( ]2 O$ Q sockfd:socket()系统调用返回的socket描述符6 U9 y0 i& ?! q% e
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。$ j& I3 n0 z0 v: Q! x+ j" s
/ `0 J' [& v1 ^6 s% B- {, _ 5 accept()" U8 H% T" S. W
头文件:
2 f4 t1 X+ _0 Y/ E; g! X7 h #include <sys/types.h>* c/ O+ z3 D9 ]# N |+ `
#inlcude <sys/socket.h>
% J2 `5 B! T& h% G3 F 函数原型:
! k) H+ F1 ^' X- t( U7 f int accept(int sockfd, void *addr, int addrlen)/ k; z4 b: r4 m1 [7 A8 ^- z
sockfd:是被监听的socket描述符
0 X. M+ Z" c% ~. s addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息9 d0 q+ l4 Q9 T0 M
addrlen:sizeof(struct sockaddr_in)
1 p# A% Q; b/ R& K X
7 o4 z: ~( [: B0 ]9 A 6 send()
: R2 ?2 q/ j. b+ f 头文件:
) h5 E, [# k0 G% D #include <sys/socket.h>. Q" N1 ]6 j. T" N
函数原型:
3 ?' I; L7 C" C: I1 A4 M$ ] int send(int sockfd, const void *msg, int len, int flags);, O! [' L1 {! r5 b' a- ?
sockfd:用来传输数据的socket描述符
7 e9 K6 l; }: O/ A9 M msg:要发送数据的指针
0 M p2 u; v: o0 O3 S* Y& P flags: 0( Z, W! f0 J# G8 G" s, ^
$ `! a2 ~2 e8 N6 v/ x4 [ 7 recv(), R; s" Q% V8 W; d3 M5 ?$ a
头文件:) H* d" H6 ^9 L0 p+ \
#include <sys/types.h>
7 y+ o: W3 A/ I+ b( n" e #include <sys/socket.h>
8 u8 o% k. B8 _1 o: i W+ d- K 函数原型:8 H- u( i# N0 G# R, |9 D
int recv(int sockfd, void *buf, int len, unsigned int flags)3 q( g- L/ s2 a( t( A$ h
sockfd:接收数据的socket描述符
! L4 Z) b4 R- h- U buf:存放数据的缓冲区0 s7 v* S7 N+ C0 `* Y
len:缓冲的长度 R) _. s: D4 f
flags:05 B0 W: [: c) }2 c. }3 q4 h$ e
7 }( \" N& _& W9 Q: o 8 sendto()
( F; A3 |) |4 N" d6 k0 j* J 头文件:
5 b4 |9 |2 ~; u# S" P$ O: s #include <sys/types.h>
% u6 K0 U% A, X/ ?) u #include <sys/socket.h>" Y1 X$ C- [0 ~& g( f
函数原型:
, l+ x5 |) K o1 }: S* |1 b int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
, @' p6 r* s l" A; I; l 4 X X' E# T6 j! y/ E& X+ d2 N
# ?9 f8 S5 e* \4 I; k9 T 9 recvfrom()" f* ~ ~8 V4 C% Y! |$ B1 f
头文件:
5 O, i2 c( Z1 { #include <sys/types.h>
6 B+ u$ l2 O6 d! b #include <sys/socket.h>& j5 x; f! m0 Q( W R
函数原型:
" u ^0 a6 |; l1 x; l' h int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)! Q$ F/ P4 _: z. r, O
( T( A- |! l/ z9 D2 N: Z O1 C+ f! S
& A/ F% T( L1 h0 y
10 read() write()2 R( s# |& N; g' [/ W' t
int read(int fd, char *buf, int len)
% m$ v( ^9 X4 k' t/ _: o0 z int write(int fd, char *buf, int len)
* M' a4 h/ I/ k5 X- h( m 0 A* D, A {% [) P9 \& u% ^
11 shutdown()
! S: v3 N3 ?% h" l2 y* Q close(sockfd)2 l+ L; \6 I' C
int shutdown(int sockfd, int how)* X4 g; e9 F5 \7 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等) 7 H: ~: z! X1 d3 T$ x
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
1 p& b7 ]; ^ k* _% ]3 I<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
- }. X# J" H0 Y; J" v' b<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等5 P5 D+ j2 R% x; M
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等; L5 q( c" N. s% P z& }
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等7 [1 q4 a3 h( `1 ]/ ]% g1 e
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件5 }* j( p! |# Q0 l# w8 i
% D S( D* I* h t5 n
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
8 t3 i" {+ l+ p: ~9 D+ g8 }+ o0 Z#include <sys/types.h> - L( v; g1 U: V8 f( |- D$ i+ {6 ]
* K. M# f0 [6 J" e3 X#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons* T J( U* w! |* {$ h
#include <poll.h> //poll,pollfd
4 G6 _6 V$ ~0 H% k1 B4 d; c#include <arpa/inet.h> //inet_addr,inet_aton
$ v7 W+ ?2 i4 I/ Z2 F#include <unistd.h> //read,write |, p& q& U- i" i# u3 C- ]2 ]0 Z
#include <netdb.h> //gethostbyname% D6 N5 E$ o) s+ e1 l- J# U: l( Q3 \
, p3 H Y" d& A. C
#include <error.h> //perror
. |2 u0 n* ?: {#include <stdio.h>
) c1 J6 i6 [" L+ b8 D#include <errno.h> //errno3 e0 m$ i8 y6 m8 y) p
7 Y, H- V: @3 M" c, B2 v p
#include <string.h> // memset
# ?( k; V( e; w; e' f#include <string>5 ]" E: r! K6 `0 _' U5 A
#include <iostream>/ X' w/ q' C. u- O" P; k$ k& h. M. A
% [4 S! E9 H3 v* W |