[size=13.3333px]一 三种类型的套接字:% R; r: B7 a+ U$ x# Z/ \8 ?
1.流式套接字(SOCKET_STREAM)
y, f% B5 T# \8 S5 h; Y3 ] 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。2 N) S' x1 S% T: f, k5 b. Y8 }
2.数据报式套接字(SOCKET_DGRAM), R5 ]: v: j+ O
提供无连接的数据传输服务,不保证可靠性。# e6 E, T' @) y- } y* i2 N
3.原始式套接字(SOCKET_RAW)0 ?; I* g f" U: T! U$ v9 g+ a
该接口允许对较低层次协议,如IP,ICMP直接访问。( I( R, Q$ X+ Y. K8 m# u# n. {
0 b) q' y; }+ X: h% c二 基本套接字系统调有有如下一些:6 L u& [! s& K& y D
创建套接字: socket()
8 T& E$ c: W) w+ W% v 绑定本机端口: bind()
- A3 h4 ^4 q0 X$ m, O @+ E 建立连接: connect(),accept()
* [& a# J% B* g8 \; r7 P- ?) { 侦听端口: listen()2 a' W) f# }4 w2 g
数据传输: send(), recv()
; k0 u9 D& y% ]# U7 m) X/ U 输入/输出多路复用: select()6 x) s) z" d# E1 _9 |1 J: y! _) Q
关闭套接只: closesocket()
! |, q# L( s9 }0 g & [* J' c5 E" ^! \8 `8 G- }/ d
三 数据类型
8 f+ G1 C3 h0 T8 L, ^ struct sockaddr
- Q+ }0 S; I; M. d& y) Y: Q6 }6 z {4 W+ P' {7 S& @, {' P, @: b' f
unsigned short sa_family; //地址族, 一般为AF_INET
# U( Z, O ?# c) c& S3 L3 m char sa_data[14]; //14字节的协议地址
, J& Z# B. V9 v h! n4 R; J }$ p6 }5 z% J8 [+ }- i2 K
( b. V; {+ S. C9 f: t' T1 f struct sockaddr_in$ Q+ _- c% _. ]1 i
{5 N! H2 z k9 _1 D. W
short int sin_family; //地址族
9 W4 ]1 b/ h$ c3 v unsigned short int sin_port; //端口号6 B. F3 K/ A2 b. z
struct in_addr in_addr; //ip地址0 c2 u- H7 I; E$ x; E; t3 Y- ^7 a
unsigned char sin_zero[8]; //填充
$ ~& }+ G1 v X# K. w' j& L }
( }# i+ m) P [6 x$ Y
$ |3 ~8 d% J+ T8 `* U四 常用函数
( L! ]. V) A% g* ?! [; j# X 1 socket()" [/ F: h* o4 g; o) ?1 p
头文件:
- |, g/ T# B# x* j" L0 B #include <sys/types.h>( D$ y8 S# R+ b
#include <sys/socket.h>6 G, e; G; b: s6 O4 r; A9 j9 M
函数原型: F4 ]$ N' ^7 V4 ]+ l+ b. ^
int socket(int domain, int type, int protocol)
* t1 D8 f6 d/ \ domain: 协议类型,一般为AF_INET- ]4 v9 {& ?5 G% Q# p0 @( o" y
type: socket类型4 V& s% |/ h. c% a3 N/ B
protocol:用来指定socket所使用的传输协议编号,通常设为0即可6 R/ N8 l8 _$ v% Y/ I Z3 d& ?; q3 e
: ?. m: q1 o% i, ?
2 bind()6 Q3 {. u8 @& g( u- \& p5 O
头文件:
1 a5 q J" b/ s7 H" k #include <sys/types.h>
0 K. {0 G/ O/ R2 z7 n4 A8 u$ K6 b #include <sys/socket.h>' i$ j1 v( J- {6 _/ {
函数原型:3 M ]% L5 ~# q9 Q/ `$ x
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
2 g2 n% e5 p# [0 Z sockfd: socket描述符
- t4 Y" o [$ P9 g- d( T my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针 W$ b+ a- T/ [% D
addrlen:常被设为sizeof(struct sockaddr)# t `# K B8 k" T* N; j
1 \- F3 |# A$ N 3 connect()
1 i; Y3 X8 S: I$ u 头文件:
8 A" R2 l6 i5 s% `/ U #include <sys/types.h> $ D, S& L: {: i- N! r [3 N v8 |
#include <sys/socket.h>
, k5 r4 t0 n4 @/ ~1 }$ c3 K8 R 函数原型:' G1 X7 K: }& Z6 p' [
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)& B @' E2 o+ A0 c) o# k' L
sockfd: 目的服务器的socket描述符- l% ^$ {9 p% o+ R3 H
serv_addr:包含目的机器ip地址和端口号的指针7 E* |+ Y5 G# {
addrlen:sizeof(struct sockaddr)
6 W8 [( h* D* D6 B3 @6 Y
" K( V" e3 K. M/ w 4 listen()$ E7 ]/ g1 Y- l3 p# S
头文件:8 O" {. e H7 `' L, `9 I
#include <sys/socket.h>
' S/ ]1 W" N; @* q 函数原型:
/ C" f, G- r9 f6 i% p int listen(int sockfd, int backlog);9 r9 A- c! M& m
sockfd:socket()系统调用返回的socket描述符: Z8 Y$ G% Q" j9 d7 z5 o
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。
( G5 t# M) D6 C9 D" q' x
; z% a9 \+ O: Z& z% s 5 accept()
5 J* D; l. ?6 j c1 o' h 头文件:
0 {/ y1 c& [9 ?& W #include <sys/types.h>
, }" F4 r( r( x8 o Q+ `4 }$ f #inlcude <sys/socket.h>" z1 W: A% _/ }4 d6 d2 Q. H0 b
函数原型:
4 N6 M2 q s% m& e7 X$ { int accept(int sockfd, void *addr, int addrlen)' {# z, [* J$ z, z, E( @ J
sockfd:是被监听的socket描述符
. Q+ A( q. u$ X+ a+ D, h addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息+ I; \0 u% [! q
addrlen:sizeof(struct sockaddr_in)
* F5 X% |) x7 d! g
: ^* s3 U0 f& d6 K 6 send()
; |/ z$ q6 p3 b3 P3 @4 i 头文件:
( R% u5 e. {* ~ #include <sys/socket.h>5 l0 E% s( Z2 V7 D4 @" \: }
函数原型:- b( g! R! U3 Q3 }% l
int send(int sockfd, const void *msg, int len, int flags);
+ v- M5 r1 r% o' w6 h7 h+ t sockfd:用来传输数据的socket描述符2 @7 f% N" a# _7 J& P
msg:要发送数据的指针 ' y( Q- `4 d9 K" R) y' E3 `
flags: 0+ u$ D: z M3 L4 f4 X9 _2 \* m
" d: a5 Q/ r4 w6 v 7 recv()
% Z8 r0 S: E6 r 头文件:
. E: Z- ?: e- V( S0 f #include <sys/types.h>
+ A7 {5 D/ e Y& X$ x( q4 B #include <sys/socket.h>
5 R* r/ {; L9 O( C" J 函数原型:
4 n0 b5 _5 b [. S+ p. X* ]7 G6 g int recv(int sockfd, void *buf, int len, unsigned int flags): x* v3 M- y; z! u: w7 F8 }
sockfd:接收数据的socket描述符' k: i$ ]) F T4 p
buf:存放数据的缓冲区
; z; O5 d8 y( v- b8 Y* C len:缓冲的长度, l, _# Z) ?( c
flags:0, w* K" x* @/ c; ?" o- h4 P' Y( Z3 E
& D/ M% ?: J( q 8 sendto()
" h1 W d: `- d! ~& s4 F# L+ e+ d 头文件:; \6 {8 G- Y+ {6 A' t4 S! h
#include <sys/types.h>4 }5 k; E5 t. D q0 s
#include <sys/socket.h>
& r, G1 c. }! g 函数原型:9 O( q9 f, k$ ?- B5 W2 [: |
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
. J' r3 B3 t5 N# c( k
* i# U8 x% n; y/ o7 f, w
0 q9 X4 g- N6 m4 l$ O 9 recvfrom()
( {8 h+ {% b+ N7 B, J$ a 头文件:
1 ^5 X. c( k" L Z- {# w #include <sys/types.h>
3 l1 ]! P- U' N+ k& ?. c9 f9 Z #include <sys/socket.h>1 F* q3 X' V* o, O* V; F7 O; q, `
函数原型:5 `" L6 [+ Q6 N/ ]6 U0 f' P
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen): b6 R2 V6 a5 X% b: `
2 u h! L7 b2 v3 \4 j
2 ]/ A& r) D8 U5 c+ f8 s" B E7 t! Q; o! q
10 read() write()) Y3 C d0 Z8 J
int read(int fd, char *buf, int len)
' S( _$ M4 c4 {% v# h5 ~2 O int write(int fd, char *buf, int len) p) L A# D* Y' b: Y. p
2 b* k- ~+ N% X; Z$ s! d, x 11 shutdown()
9 N! p7 @1 X! D close(sockfd)# |0 a1 w0 ~& a; U4 c
int shutdown(int sockfd, int how)
; O) m/ T( D; L" d' }& F& Q1 Z* u----------------------------------- [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等) 1 q6 \1 ?- h- g! l7 I
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
) B K. N; w" | @ [<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl(). c# R+ R- L% w, H( ~
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
8 K- d5 W& e" I5 A! k3 V<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等7 N. Y+ }% B: N( D( [8 L g
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
+ ~ V0 w# n4 b, H/ M6 e3 X& d<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件
9 h0 l4 k7 Y$ I8 R' ?. S* z. C: K; a/ ^( _# u) d
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等7 W1 |+ V7 G. t7 b; x7 ?/ n5 R. e6 c
#include <sys/types.h> 4 Q. h7 z. N+ {% w+ T H+ O
- \* m* f5 `# t# [ o7 \
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons& ?; r: V6 G, ~$ T1 A; T4 i( _
#include <poll.h> //poll,pollfd8 d: f' ~+ J- ]& j9 R
#include <arpa/inet.h> //inet_addr,inet_aton5 n8 H8 g! Z; u) n! p0 t1 H
#include <unistd.h> //read,write6 D4 x6 a, t! J1 L% q
#include <netdb.h> //gethostbyname
8 x7 P! s" C& X' f" F' \; @, C2 ~7 z/ B
#include <error.h> //perror- h" G% S% w; g4 ^7 Z
#include <stdio.h>
' }4 g( `; ~, _: n1 F#include <errno.h> //errno
5 e. y$ O1 z% P& \2 I: E, k c7 J0 {$ B7 a, X# I
#include <string.h> // memset; H7 D r7 W' m. m# M
#include <string>
7 j$ U6 b" a: Q8 ]6 K#include <iostream>
# Q6 @& r/ ^, u2 I' }( R3 A, e% t& D$ U2 k" x* B
|