[size=13.3333px]一 三种类型的套接字:3 Z0 c! x$ B% Y: t$ p! v0 m
1.流式套接字(SOCKET_STREAM)- R) D8 a9 o z/ W$ O) f
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
1 g: i4 w# q% `7 _3 w( A2.数据报式套接字(SOCKET_DGRAM)7 T/ l; a. l! ^( D7 L
提供无连接的数据传输服务,不保证可靠性。* H N3 l! m' V& {0 B& G
3.原始式套接字(SOCKET_RAW)) |# b' ^) w" C2 V" X
该接口允许对较低层次协议,如IP,ICMP直接访问。
2 P a' s) _ J- }7 Z4 }' L6 _9 d! g$ {/ T5 T% t: O
二 基本套接字系统调有有如下一些:
( {2 K F& q* ~" N( |+ l 创建套接字: socket()4 y( y Q1 T, K; o% H5 |
绑定本机端口: bind()6 c2 L1 G# ~3 i! R
建立连接: connect(),accept()
3 j' f% f6 @- E- U p; ^0 p 侦听端口: listen()0 F7 p% T( C# @& S6 a2 H8 J3 x
数据传输: send(), recv()9 ]9 k& h" n( m% B4 B h
输入/输出多路复用: select()3 j h0 ]8 R9 P6 r
关闭套接只: closesocket()
9 ?& m6 t3 ?' q: | # \9 g& P/ z" X5 D; P: h0 d: j
三 数据类型: b, W0 A6 ]/ e* a
struct sockaddr
) o* v$ s1 O% T4 G( V" v. G; [ {
3 x7 [7 ~2 {: D0 _3 v/ @! o unsigned short sa_family; //地址族, 一般为AF_INET
6 `9 h2 Z5 _; |9 ~9 _5 ]( q: r, T- Q char sa_data[14]; //14字节的协议地址7 ^5 J' t% d* |/ u) ^( t
}
' y: S+ x, b1 c, {! H
9 K/ X: s( {/ S6 l struct sockaddr_in
, o. L' ^9 P" ?! E% v5 i! E. m {; D8 @) E& M5 v& T
short int sin_family; //地址族& w2 H9 i& _% g* h
unsigned short int sin_port; //端口号
& j/ F' M2 Q3 s: `5 b; s struct in_addr in_addr; //ip地址
6 e9 h7 J$ F' C4 c7 d8 i unsigned char sin_zero[8]; //填充
5 ^! p) t/ e% \1 _ }
9 ?0 {6 n- v0 s" Q) c9 y _% h/ O$ {! [! e
四 常用函数
3 g$ `* ?$ w- M, p5 m/ ?$ _2 z 1 socket()& N% H& ^# o( e9 @
头文件:
5 G4 \$ m. f" j9 E% Z( X #include <sys/types.h>
5 G6 A. ~! ?. D #include <sys/socket.h>
. v5 S, P. T& I; z# s 函数原型:! E; g- E+ i( Z5 S2 q6 _+ p
int socket(int domain, int type, int protocol) j9 I C% h- W( y2 N
domain: 协议类型,一般为AF_INET
! y. H& \: X2 U" ^7 b type: socket类型& q4 _; ~6 p% a: a
protocol:用来指定socket所使用的传输协议编号,通常设为0即可. _% b, U* U2 E" Q- R; b
5 n+ O, U5 ~2 d! }$ S' u; B
2 bind(); n: G: R4 c* m* R5 U
头文件:
* Z; a5 o/ ^: _9 U0 @! a+ V: y #include <sys/types.h>
4 Y+ r R6 N- ?* D #include <sys/socket.h>5 ]1 J4 ?, y% U. |) \& d# Q1 H1 Y
函数原型:$ K6 s$ N. h8 t6 ?% |7 _1 }
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
0 R* H' D+ ^3 M sockfd: socket描述符' G& e: z6 @$ G
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针( t( O% y, Q; \2 ?* z, X2 ]
addrlen:常被设为sizeof(struct sockaddr) f6 i9 W& q1 B& H! s
! r% p5 i9 ^( N* j* k9 Z 3 connect()( _! d2 ~1 X# m6 K3 S1 n
头文件:2 C0 |& ?& @5 ?9 v, G; z a8 L9 |2 x
#include <sys/types.h>
) U2 T# K" l: R3 I7 d' _% l& X #include <sys/socket.h>
5 l* G4 K p6 Q4 G7 C- J 函数原型:
9 p$ r; b& ^( I: I5 j int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)1 N+ I3 A) r; U" p; |4 c) Y4 @
sockfd: 目的服务器的socket描述符
1 S, f. h0 w6 X serv_addr:包含目的机器ip地址和端口号的指针
6 l8 Q1 l; O4 T addrlen:sizeof(struct sockaddr)
) S( z) Z |" j K2 ~, n5 `$ o5 @2 Z) [2 e4 Q( r
4 listen()
2 D: x& G8 `: l: W5 W+ x 头文件:
/ ^5 k" r8 Q" o* U% b' J0 | #include <sys/socket.h>6 B3 Z0 i' z; a5 v
函数原型: a) `2 v+ t" H
int listen(int sockfd, int backlog);. r5 O8 ~1 w5 z- R# h) [* r
sockfd:socket()系统调用返回的socket描述符
: f% K! o$ C6 ~# T) r( E. Q backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。
$ M% h4 j+ A4 N# [( j( F
& j" W/ |- ? T6 h 5 accept()' D9 Q" M! L, G/ q
头文件:
$ ?6 U$ d0 y$ y9 c* P% A9 J4 C, J #include <sys/types.h>
3 n7 M& k2 q: c6 M- v9 E0 A( @- l# Z #inlcude <sys/socket.h>
1 E+ s* C* ~8 N! P 函数原型:
9 }' y s/ T6 B int accept(int sockfd, void *addr, int addrlen)
% F3 f) O3 d: h+ L8 b sockfd:是被监听的socket描述符- n' V6 J' `; ]" s- o
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
) X" v G; B0 V7 x1 M1 {- J- g addrlen:sizeof(struct sockaddr_in)
$ y( P% D/ `6 x1 o
( ]) A, K0 I; k+ \: ^& Z 6 send()0 |: H7 B3 t- }! [
头文件:
# \* z( l7 A" b' Q #include <sys/socket.h>- s: D3 A6 U0 u' ?: g
函数原型:
6 f; `1 [# \& `7 m1 z2 X: U( `! o int send(int sockfd, const void *msg, int len, int flags);
7 N! e& o5 o) \' l2 X T: q sockfd:用来传输数据的socket描述符5 S, R9 A% x0 A' X- K) ] ~
msg:要发送数据的指针
( ?: O8 b4 h+ o0 V flags: 0
3 M+ @3 n" L2 p8 |: V 0 j% o5 s: t9 E! }' _
7 recv()
( F" H$ y0 _8 z' r* l8 f 头文件:8 ?( w+ I' v2 x+ g: X" B
#include <sys/types.h>
9 q7 N' Z- _' M/ L+ s7 M# C1 V #include <sys/socket.h>
D( v; y @6 v2 R, d 函数原型:. |( }+ |9 I2 U% P o( l
int recv(int sockfd, void *buf, int len, unsigned int flags)
: V: Z$ A/ a* ^9 e' ^ sockfd:接收数据的socket描述符
; X8 ]4 A) U3 L2 o# B( B buf:存放数据的缓冲区3 K: F# `3 F* o, v9 T* U: }* n+ W3 S
len:缓冲的长度
6 f h- i# B- S! Y4 ?6 n flags:03 _* |2 v$ P4 Y6 A" _; R$ x
. {4 L4 d3 u3 o$ P+ K: g7 D* J 8 sendto()2 r& B3 S' l' A) p- ?
头文件:
# j$ P& U3 ~& h3 \" Z3 P7 R #include <sys/types.h>* g. b' |0 g( o- u2 v$ F
#include <sys/socket.h>- a" ~( x, U- z* _( r3 G
函数原型:8 q: G2 E3 P) L C0 L* H o) N& J7 l
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
% U7 Z% P( f% ]; x! m & u' k1 i" R2 M* s
$ z4 ~; n0 ~ q0 d, z/ B; W) o) s 9 recvfrom()0 v$ {: Y) @5 X8 H6 i+ u
头文件:. i2 U8 I5 U$ S
#include <sys/types.h>, R L; Z b9 J: ^0 _( {
#include <sys/socket.h>& Y) R( `' J E" J9 }2 O3 T, w+ I
函数原型:
$ \% u. {: o& s- ~7 P+ j int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen). ^0 w. s3 g+ ^4 _
; |' H# j$ f; L
! L: e2 r, ^0 K# i 10 read() write()+ O7 n$ l" q. @) _
int read(int fd, char *buf, int len), L" r/ L9 _; x. N" D( ]
int write(int fd, char *buf, int len), O9 B- @& Y9 ~8 Y$ n
9 w+ i# Z( Y" Z" m8 e* R
11 shutdown()
; d$ C: M! J$ T0 T# G close(sockfd)
, `) i, e9 |% N6 Z0 e8 X int shutdown(int sockfd, int how)
- U4 j1 J) T" J+ B S: 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等) " W9 C5 N% q. l# O( a$ C
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
& F2 H7 O2 }) P1 P* E: G; B<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
3 @9 [5 h. h7 W; d/ V& _6 j6 U<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
; ?6 K3 L. `1 C<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
- \* O: h. S1 u9 e i<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等) ~6 F }, s* v% v% c
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件
& w9 A2 d6 w8 {+ ?$ F' A
! o5 M& m# H8 |7 k[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
1 P D1 I- d+ W! W& j4 P# Y2 v9 {#include <sys/types.h> ( Q" `6 i. V- x6 S0 ]/ Q6 N
2 ^ b" A/ H' E0 O4 f
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons% |/ a/ L$ h, S: T6 O
#include <poll.h> //poll,pollfd0 }3 U2 `, b$ w* ^1 I/ _
#include <arpa/inet.h> //inet_addr,inet_aton- H' K& y6 A, \' b6 W8 O# c0 d/ d
#include <unistd.h> //read,write
* F. c8 s" k m6 f, b#include <netdb.h> //gethostbyname
3 D* x1 S' k$ P8 W, s- [
" |) F9 {4 A5 D+ l0 A#include <error.h> //perror
8 s1 i0 ?( W1 q#include <stdio.h>, _' v+ r9 u: M8 `. O" E; F
#include <errno.h> //errno7 |5 y/ G" u$ F1 b+ G6 e
6 N4 P" O' N6 z5 [8 F$ s- q#include <string.h> // memset
) p) p' b' F' B8 z#include <string>
* }6 ~5 f& h# T% ?#include <iostream>
; o3 J* @0 H# x& z5 z8 V: V, b# Q2 j
|