[size=13.3333px]一 三种类型的套接字:' s+ }5 E& T/ ~, b ]
1.流式套接字(SOCKET_STREAM)
c1 h) y% l0 j: e6 T! K) U 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。2 O9 E2 q/ _' t& M0 E
2.数据报式套接字(SOCKET_DGRAM)
. j7 g" c, Y2 x1 p$ R 提供无连接的数据传输服务,不保证可靠性。
3 w/ V( }2 n5 r5 x0 _4 L! {. |3.原始式套接字(SOCKET_RAW)7 H% `! Y7 M# ?& v# F& z6 u
该接口允许对较低层次协议,如IP,ICMP直接访问。
" ^9 U8 c3 X. z6 H3 n7 E9 T4 b/ W* C' J* V
二 基本套接字系统调有有如下一些:3 z3 j1 f+ G- H; ~# W* y/ n
创建套接字: socket() p: v. Y$ z& L( U7 {
绑定本机端口: bind()
6 l5 m0 C; M2 @7 n: s6 } 建立连接: connect(),accept()4 }, ^+ S. c7 A) A; Z0 v
侦听端口: listen()
$ F% n9 A5 K8 A8 B) ~% B 数据传输: send(), recv()
( x8 w9 v0 s5 u 输入/输出多路复用: select()
0 S. G% N" I4 X 关闭套接只: closesocket()# g0 R0 H$ c# [' O& v
, x. z& Y& Z4 ~: ]/ r2 C1 x* e' H
三 数据类型& K- k C/ V! Y4 T F8 T5 E) m
struct sockaddr
- }% t" R" D) D! P/ X$ l0 K {0 u: C" q" L/ v* Z
unsigned short sa_family; //地址族, 一般为AF_INET# V& m) ~" @: f: w, y7 D1 x! x" n) f
char sa_data[14]; //14字节的协议地址 N6 p$ F( d1 k8 p/ ], }$ J4 v
}
, ^% J/ e* H1 s2 r6 H; r1 ~- v8 \ f: P- k
struct sockaddr_in; d; o% B. W4 B+ h2 i& O0 l
{$ {# r" ?4 _* C8 _4 P: e0 S
short int sin_family; //地址族2 ^* R3 }# Z3 E+ X. a# b( m3 W
unsigned short int sin_port; //端口号
8 u- P- p9 N) g3 e! s( ~* f* b struct in_addr in_addr; //ip地址
, D: r; y' V( C" b( J unsigned char sin_zero[8]; //填充
6 o$ Z. p9 T: E& i( R }- a6 u2 H% B, \/ {, k! B
4 `, y+ {2 E& M2 a四 常用函数1 K* C/ h+ M( n; R
1 socket()
& x4 \, K4 [( ~3 W* c& Q 头文件: 9 R+ Q; a/ L! w* y8 S, I
#include <sys/types.h>
. T* |8 L, d9 O- e' z2 q5 n- T #include <sys/socket.h>, n0 d3 P: \, i; Q' z
函数原型:/ G" D1 U$ Y. K2 H
int socket(int domain, int type, int protocol)+ i& z0 `% T. C8 x q
domain: 协议类型,一般为AF_INET
) s t& Y0 s& i) @ type: socket类型7 ~4 Q- `0 _: p z* e* h4 m, }5 J
protocol:用来指定socket所使用的传输协议编号,通常设为0即可6 {+ U, P- S( Z2 T8 [
) W' W! `# F5 {) w4 ^5 f0 q 2 bind()+ Z8 v6 M' N. O
头文件:6 d" q1 R3 r) x8 J# n# p$ U
#include <sys/types.h>
0 v$ S6 y6 C3 v/ s' ]7 {9 K- N( x #include <sys/socket.h>. k5 N4 i: ^6 T+ c/ s, t
函数原型:
9 x* G. Q2 p2 R1 I% B! r. N0 |8 W; B int bind(int sockfd, struct sockaddr *my_addr, int addrlen)3 v' [9 g+ C5 C8 ?: j
sockfd: socket描述符
" Z8 a+ P! z% F my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针" u9 l) F$ `# Q( u
addrlen:常被设为sizeof(struct sockaddr)& P, i% @: F( A9 y$ n4 L. o9 y
5 q8 }" j! }7 @7 x% C
3 connect()
, t# @& W1 c! ~6 G. J! J; E5 C7 I9 S& n 头文件:
3 P7 [; `. U, n #include <sys/types.h>
9 @ D2 n# N) x7 e6 [2 ] @+ E5 P9 q2 | #include <sys/socket.h>
: b. ], n+ E( }9 d 函数原型:
9 Q0 w1 v( @' o6 h" m3 R int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)3 d/ v& q5 e7 Y) n8 @8 [7 v
sockfd: 目的服务器的socket描述符
$ w& I7 K, r% F- v; V, C serv_addr:包含目的机器ip地址和端口号的指针: {2 y$ }0 u9 r
addrlen:sizeof(struct sockaddr)! ?5 P4 h+ M; U, v: S' F
% K! X. f# Z: l" f
4 listen()' i: `8 u8 }2 v5 k* R
头文件:
3 a" c* G; |, v* }" j9 e& G #include <sys/socket.h># ?' l* ?! I# x7 }0 @
函数原型:, L! v9 C W* e
int listen(int sockfd, int backlog);
8 x X9 o" j: K$ g sockfd:socket()系统调用返回的socket描述符; W5 k& w, a' K8 q
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。
' c u5 Y/ N$ _9 P
: ~2 W2 b* x6 m 5 accept()2 U7 S+ L7 W5 L+ c6 i
头文件: ( T) D' s; j1 h1 M6 i
#include <sys/types.h>
5 y/ W- ?+ C" U1 K ]2 j6 s3 S #inlcude <sys/socket.h>
* u& |+ f2 i& V6 e 函数原型:
2 I. q( t$ K' g+ t0 N int accept(int sockfd, void *addr, int addrlen)' h, Z- G$ Y' T$ R6 [
sockfd:是被监听的socket描述符
. }/ y5 J3 c, k addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息% O9 v$ l L; V0 k' z
addrlen:sizeof(struct sockaddr_in). \* B0 Z# F& M4 @
$ o; s, `4 T. g' S" z! x- j1 ]8 A
6 send()& L g" O$ _" t- f& U5 M
头文件:7 L7 V7 p1 b+ J# p4 c$ i k
#include <sys/socket.h>
* m+ a( D5 o" c Q6 p& d 函数原型:; V1 N. ~: F2 Q0 k. x6 o
int send(int sockfd, const void *msg, int len, int flags);, q) e- Z# e: a$ o$ C2 B, j0 n
sockfd:用来传输数据的socket描述符; m+ B! p, }" p# s0 R/ r4 b( A2 s
msg:要发送数据的指针 ( E7 d# T2 h/ s4 x( z
flags: 0* N {% c+ o) ]
, A. {5 W6 v6 Q3 J
7 recv()0 M3 F! j' k1 O4 R+ \
头文件:( U: S- D/ b; ]$ q! y7 Z( r$ d& X
#include <sys/types.h>
+ Y4 v- b* H3 p/ X1 c, Z! X #include <sys/socket.h>; Q: ~7 w E5 S7 Y6 ]. q
函数原型:
- ^' M7 Y. h8 |3 A% y int recv(int sockfd, void *buf, int len, unsigned int flags)9 m, J2 }) r8 y& G: l+ Q' {
sockfd:接收数据的socket描述符* L2 G" \8 a5 `# j( b
buf:存放数据的缓冲区* o) }- w+ ?! |1 E6 I4 a
len:缓冲的长度
/ A6 P! @: X. F9 R flags:0
' D+ z/ @, ]4 L" a5 h- e3 m8 g% I" G$ z. a6 z4 g
8 sendto()
$ x9 o- k' k( x 头文件:: u7 A/ @1 Q7 F5 D
#include <sys/types.h>
$ v3 }- Y- Q) \& Z! t+ L #include <sys/socket.h>
$ q( L% E- R0 p6 U# R& b 函数原型:
/ e' ^1 \6 W; d( s int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
& H7 e4 P8 i% c# b) E $ }4 b0 s$ t+ @: f% T h
7 F! s# Z7 w" t1 q3 w; @) w3 F 9 recvfrom()
9 H: p1 u' K# \+ H0 f; G0 z2 a 头文件:5 b- r$ Y& [: ]
#include <sys/types.h>2 [8 H4 j3 S8 D' v& d; m
#include <sys/socket.h>6 G+ J% V. G; R6 b
函数原型:
3 c5 ~$ |( p6 \/ @% Z, Z. P$ q int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)% O- }1 C5 q# W7 F2 |# k& u+ ]
( U0 ^ P' x2 z
1 v) [: L+ h0 } 10 read() write()0 h+ ^. D _; c3 v
int read(int fd, char *buf, int len)( H3 T! l. N) q/ c& B
int write(int fd, char *buf, int len)
" }! L# M6 A; K9 k, F% f1 m% }! X # E9 A! }! |. U- G5 b- z
11 shutdown()5 t$ `6 A* Z5 B& w
close(sockfd)
. z7 w3 i9 x" X7 f3 Q; r2 X/ r int shutdown(int sockfd, int how)
; ]8 c, _2 o6 i% I----------------------------------- [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等)
4 J" N# R8 |3 P; ]$ k3 X6 F! b<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
- x! P( g/ E2 J6 |, X<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
1 c: S6 f8 g4 t2 a* z<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等+ H& O! K% w2 o7 ~8 f, m9 y
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
- j7 ]6 K" z8 c4 v8 S; ^<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
/ E6 W C0 n$ O" N4 _<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件( |6 |5 {* n! j4 J' c2 q/ \8 G
+ k# X) m7 g, k
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等. c( t) @0 B( l% ]9 F. Q
#include <sys/types.h> 2 q% a, [/ ^4 U' W
& X, ^* ^2 G- v: L$ G4 ^
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
; ~) P0 i Q9 b8 E( G& D5 W0 L#include <poll.h> //poll,pollfd: p6 L! N' `; z, E2 }! V- p7 b8 j2 O
#include <arpa/inet.h> //inet_addr,inet_aton
) |0 Y2 H0 |) \. e* |& r7 u7 i#include <unistd.h> //read,write6 j6 E$ g8 o6 A# A6 @* g6 s
#include <netdb.h> //gethostbyname
; C3 G4 j) W# j4 g6 @; x$ g1 @6 g, ~0 ^+ O: M E
#include <error.h> //perror
1 y! ~3 w( h; L4 D6 m#include <stdio.h>" P+ n* s8 P9 G% j# @
#include <errno.h> //errno- K% V* B: Z. w: d2 t
5 _) t/ [% _. H# M# T#include <string.h> // memset
$ C6 W5 }. V0 F; M#include <string>$ X6 w# J* ^' ~. z% |
#include <iostream>
1 {9 M4 T2 ]% V- E, s' e6 g: N$ f+ d- q8 E
|