[size=13.3333px]一 三种类型的套接字:' P. D1 Z7 Z* x/ q
1.流式套接字(SOCKET_STREAM)
q8 l/ c: R( z2 E4 N8 _ 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。: F/ y, m* _; ?, O' X, z4 z: g
2.数据报式套接字(SOCKET_DGRAM) v5 m7 j) ]6 m8 Y7 W' g4 ?
提供无连接的数据传输服务,不保证可靠性。- S4 o- w. N+ E. i$ q/ r
3.原始式套接字(SOCKET_RAW)9 a; K- o9 Z$ t) g8 q7 D+ }! m
该接口允许对较低层次协议,如IP,ICMP直接访问。
f! x- Y4 r$ Q" y
/ m1 c7 m: [: ?3 V- m二 基本套接字系统调有有如下一些:
! W+ }" M( G v+ @/ W' r: o 创建套接字: socket()* x( ^# t, y2 b: f( Z2 E1 s
绑定本机端口: bind()' B- l V8 P+ ]' j2 D6 ?6 W
建立连接: connect(),accept()& b. x' z4 s2 I0 i* w I0 Y, e
侦听端口: listen()# A) T; b+ u1 Y) o8 x' \. E# ~) R( M
数据传输: send(), recv()' C- m& \# w3 {3 ]/ l1 P- }
输入/输出多路复用: select()
0 }6 T5 k' J# U, k6 a: x( h4 x 关闭套接只: closesocket()
6 o4 H7 T9 A T# V. m 9 h) ]; O' h# r" N. K3 R
三 数据类型
6 l# Z# r1 Q+ T. F struct sockaddr
3 r" w/ k8 W2 h% i# z5 J1 t {2 B: Y1 H1 ^5 x; w
unsigned short sa_family; //地址族, 一般为AF_INET3 D9 y" z3 L/ ]& `: o4 |% ~
char sa_data[14]; //14字节的协议地址5 u* ~( x+ a0 ~( W
}& h- {& e5 I- ~8 I2 X6 d
: ?' v; N% d3 O struct sockaddr_in1 e# \2 ^# T! E0 Q$ R* ?
{0 t# J! ]2 R. X' s- z9 y2 \, M
short int sin_family; //地址族! _% V; K4 |4 n! a5 X: f/ M0 m" w1 P; n
unsigned short int sin_port; //端口号
8 p; z+ J' A8 K8 z$ x f) }7 K struct in_addr in_addr; //ip地址
9 s4 O: Y6 ~- W% Q4 I unsigned char sin_zero[8]; //填充4 Q5 r4 p$ D) b4 j
}
3 t x0 ?3 f8 G x, r$ k' ?% ]2 n2 `
四 常用函数, Y0 R8 R% x5 l1 y4 ~. E. s
1 socket()
8 a4 k( S* M: ]4 z( [" S& [& q 头文件:
3 e& {$ }4 g6 x% V #include <sys/types.h>& B. \' Y5 A9 C! `+ a
#include <sys/socket.h>% W, n8 }% K5 Z4 j/ I: {
函数原型:6 a& {* j+ `- [( j1 y @
int socket(int domain, int type, int protocol)
$ J. c6 a1 x: U- U domain: 协议类型,一般为AF_INET( ?7 n* e7 \2 U r
type: socket类型
, J" c" j# `3 G/ ]1 ~1 J! y) ^ protocol:用来指定socket所使用的传输协议编号,通常设为0即可% b7 _' G1 f6 Y5 x, q+ d
3 m+ z* ?, I* }$ C! T- a
2 bind()" T- e2 {7 d1 h7 `: [
头文件:2 f) Y _" R) Y' S
#include <sys/types.h>
% a/ c$ N- h6 [- H #include <sys/socket.h>
m! g8 }4 a1 v8 w$ _( l6 O; u3 U 函数原型:
B+ G7 H: y. z& t int bind(int sockfd, struct sockaddr *my_addr, int addrlen)* b; d- d5 f2 q* y& ]
sockfd: socket描述符' F+ I/ {( W: R. p& w) U
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
2 L9 V& D, H1 w' V7 p5 E8 v8 Q( n addrlen:常被设为sizeof(struct sockaddr)/ D* }+ p$ K% E" t6 n# {1 n
: P1 L! s, O" X 3 connect()
$ `! z" e/ E% q4 j. t7 v; ~+ I 头文件:5 A1 s6 F8 h, |& A
#include <sys/types.h>
# A5 I9 g! \3 G/ X4 h* _% v$ N4 ^ #include <sys/socket.h>
/ P0 W( ? a0 h7 r; N+ A 函数原型:7 U( u" t9 o5 L4 j' d
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen); ~( ~; I1 e6 W' s- P, x; Q. y
sockfd: 目的服务器的socket描述符# r" i. Q& e' q% B% s; o
serv_addr:包含目的机器ip地址和端口号的指针
' t2 p8 p' u2 C3 P8 i addrlen:sizeof(struct sockaddr)
3 T" [# ?% [4 O
% l% j: L$ F+ b) g3 q9 a 4 listen()
! h: k9 i$ G! n: x" D6 I# y! ]5 ^ 头文件:5 `. ?0 c# Y$ T; H8 V. j: x
#include <sys/socket.h>8 }0 D' F! Q. F% T4 `1 d5 J
函数原型:. `& `/ M- X9 E9 j* I; D: f+ H
int listen(int sockfd, int backlog);1 i$ i0 l. d$ L! B1 A; [" T
sockfd:socket()系统调用返回的socket描述符
/ s: ?+ `1 F$ `7 y backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。4 V3 C3 g+ g$ A# H: M8 c# ?
. F" M1 ]9 D! _ 5 accept()
& a0 X; f0 p' F' z3 H 头文件:
, _) ?1 G- D6 T0 }2 Y #include <sys/types.h>
$ B1 w+ t; L# k0 S8 _+ C #inlcude <sys/socket.h>0 W; u3 \$ h( m, P) r( q
函数原型:
/ a) ]( y4 O- g. n5 O- o int accept(int sockfd, void *addr, int addrlen)& D; i7 X6 X6 i, w9 b0 n
sockfd:是被监听的socket描述符* p* l+ S4 ~/ D; s* j
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息& A; m9 }4 E6 \
addrlen:sizeof(struct sockaddr_in)8 o7 Y1 a- [9 o* B, H! k
" h& w) w" u$ K4 O1 j- P. A% }" ~ 6 send()- Y2 i# F8 U* [6 R
头文件:
/ G( Q! Y$ M% u* y& b2 t #include <sys/socket.h>" |1 R; `6 E# [ r/ K
函数原型:
2 \, Q, b. T- u; c+ ]& x int send(int sockfd, const void *msg, int len, int flags);# K0 Z# Q# @0 a/ z4 j
sockfd:用来传输数据的socket描述符
( |- j/ H/ b' Z5 X- m msg:要发送数据的指针
8 ]7 K. [; V Z' d1 l flags: 0/ o0 Y! E V$ c. [+ q9 s5 U# K
s, _% s2 _3 ~9 l) a 7 recv()
7 o |$ ~9 g2 | 头文件:( _) |* I* t" r6 s. n# H+ t, a
#include <sys/types.h>+ u9 P: f Z5 z/ ^, v
#include <sys/socket.h>* j/ u4 }; M i5 x# r
函数原型:
/ H1 y% y% B7 t/ r% {0 F* ` int recv(int sockfd, void *buf, int len, unsigned int flags)# w/ Y5 H2 U6 n: p4 { N
sockfd:接收数据的socket描述符8 e. @- C' g, F
buf:存放数据的缓冲区
. f! d$ L. B3 S+ c4 w0 N len:缓冲的长度
* A: T3 h# | k2 F flags:0' v7 {' w _9 @* v
' a; {9 \: j$ n c9 Q- l" N 8 sendto()
. ]2 b7 b. A* I, @$ z& |6 a7 B( \- q 头文件:! D; b8 P' D9 j; m
#include <sys/types.h> ? W2 Y6 j! E7 s! j
#include <sys/socket.h>+ n0 C8 R M- o
函数原型:
- s D! @% Y. ~1 C# w$ C int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);- f& \' ~# f* B2 N: Q; ]
0 q( f% M1 M& m* ^
) s$ l( V1 d/ }( ?# c
9 recvfrom(). o7 R+ n! Y9 Y# r% |# C3 y
头文件:5 F6 k4 Y0 V6 S
#include <sys/types.h>. K Z* @# N8 p9 P4 E7 f
#include <sys/socket.h>
/ D' C; W3 ]' B& ^ 函数原型:2 x; S J5 U4 z0 K D! o
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)3 j I9 P0 p# T/ {
1 X* m( g: n+ j) z8 {9 t6 J6 L
2 ^8 w6 c8 c" ?) W
10 read() write()
L$ Z: t+ L8 t( ^6 U; K int read(int fd, char *buf, int len)2 v2 {/ I% k# i
int write(int fd, char *buf, int len)
( b; L$ n9 [9 h% G ' s/ B6 o" O3 J& W$ R& o5 E7 d
11 shutdown()
! e4 i0 p0 I; Q close(sockfd)# @9 e7 M a9 L0 ]0 r" Y
int shutdown(int sockfd, int how). j7 E/ K+ y2 J1 P2 z* D8 l2 }) d
----------------------------------- [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等)
( P# g e( f! [2 ` S8 f7 D<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等2 r. Z# D: a" B- p( x, G
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()4 b5 p. u4 g; f: n j: H+ q. Q
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
% C1 F2 b( d/ }* N7 G<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等, J% O; J* w! x' v4 j8 w$ {# C, N
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等( @, Y% W/ v% h9 K
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件0 H- U& V- c& T* z
- s+ `8 N' T t) B5 y8 o4 ^
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等: C. i( i: w9 J
#include <sys/types.h>
+ p& J# @3 F* p+ |/ G* T5 v. ~- m, H6 p' D3 u
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons2 h1 E& G0 F9 ]
#include <poll.h> //poll,pollfd, a, ]$ T3 g) _/ o" S& P
#include <arpa/inet.h> //inet_addr,inet_aton
( T# h( y; J; t#include <unistd.h> //read,write
# M+ W1 S) F- K! ]( e& I#include <netdb.h> //gethostbyname
& w) r% S4 e9 L& E" L, W7 I
* B# [' ^5 o2 ^6 }! I3 R5 K8 A1 @#include <error.h> //perror. W( b& @+ T3 r4 k
#include <stdio.h>4 X$ G" C: f! H) t# W
#include <errno.h> //errno
. b1 y" }2 s: ^( {5 Q1 Z2 g) b. }& m5 |; |; M4 Q+ F8 E' V9 X
#include <string.h> // memset
+ s- S0 n' _, D D#include <string>& v: G" _* d( Q t
#include <iostream>
* F0 \* e4 p8 e1 }) e- [+ d3 Z/ F
|