|
[size=13.3333px]一 三种类型的套接字:
7 `6 J# J8 v% |, m9 H# U* u1.流式套接字(SOCKET_STREAM)
$ _, |6 i' F1 y% J9 C: L 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。) n$ j# q$ g( {* c8 ]: w
2.数据报式套接字(SOCKET_DGRAM)8 D+ |1 D3 z0 @- @! E
提供无连接的数据传输服务,不保证可靠性。8 j* i0 D( q! j4 S) b0 \
3.原始式套接字(SOCKET_RAW)- F: k4 p7 {8 d7 Q6 r
该接口允许对较低层次协议,如IP,ICMP直接访问。% _) o* F5 x" b. [! m
+ y# B' W7 t8 e" @
二 基本套接字系统调有有如下一些:
2 p, s* f' a/ l1 p( g# [6 S, | 创建套接字: socket()5 d5 v' z5 j c
绑定本机端口: bind()
. X+ y# j9 V: _ 建立连接: connect(),accept()
6 {# a! P( c; ]3 j6 R* D" A 侦听端口: listen()
' N' {, O. W9 H( n" L+ t: q/ \ 数据传输: send(), recv()
: F: m. q$ y+ \7 t: l. P 输入/输出多路复用: select(), |7 V" |. Y( E% u3 Y8 B! A# X
关闭套接只: closesocket()
: @# a' ]0 O, {! d5 b
8 ^# z; S% P K1 n! y- p三 数据类型6 I# S: G0 h% n3 R, Z/ H
struct sockaddr
) J5 e0 y4 `; }4 S: G4 Y {
6 M% E6 z+ @" L# z9 z3 ` unsigned short sa_family; //地址族, 一般为AF_INET- ^' n% {" h- ^' p
char sa_data[14]; //14字节的协议地址
& c/ _. [3 c* H3 h } z, S J2 r# G/ X5 P" m
1 b$ f3 o4 v2 R' x' ?( \9 x
struct sockaddr_in
1 z4 O/ w8 U2 ] {$ h: U n9 f" i0 k: K% b% |0 N; A
short int sin_family; //地址族" a) \# X0 v/ I5 z/ s
unsigned short int sin_port; //端口号8 k+ H, K3 t5 d$ R* b5 w9 ~( L
struct in_addr in_addr; //ip地址
v. k% v9 c; i1 i. _: }: j unsigned char sin_zero[8]; //填充3 a5 b- y0 G, G$ q: Q
}4 t; L" G5 v) U1 ]# u" e
9 O9 T. b, R. z+ L% u/ |四 常用函数9 p: Q6 u9 E B
1 socket()
% d' ~. S; H0 Y7 W3 w 头文件: 5 c. }" Q6 x8 t; o6 e# `3 s
#include <sys/types.h>
2 }+ Z% X( {8 B5 O4 M #include <sys/socket.h>
7 L- ~4 f8 x/ |. | o; ` 函数原型:
: N* X! h* y1 x6 c. y t int socket(int domain, int type, int protocol)# z/ q* X9 g {! [
domain: 协议类型,一般为AF_INET
8 Z" `% q/ m1 }3 d% H& ?$ U( y type: socket类型 n' N" A) ?& z$ W- I
protocol:用来指定socket所使用的传输协议编号,通常设为0即可
# R6 f1 Z/ d" H% e
7 o9 g/ T5 V( R* w U# D9 X 2 bind()
4 K2 H$ x# b' b( s' ?! p 头文件:
1 E$ ?( z& `+ M. [( ] #include <sys/types.h>6 B3 Q. `- e: Q9 E5 V0 f
#include <sys/socket.h>
1 E2 k/ B1 J! V! _ 函数原型:% H$ L' j, P+ h, ]7 _/ Z# `
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
5 ~: u- h8 p: G' L# h sockfd: socket描述符
+ D% v0 @1 p' _; [' A) G7 M f0 [ my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
g* G) S; `/ ] addrlen:常被设为sizeof(struct sockaddr)1 T$ Q) |5 L9 G) l) q9 C
: T4 u+ o; `! a6 L( }
3 connect()
& Q3 T6 _* g- [ 头文件:! t& X9 n! @" G' Q s) s! o2 u3 ]
#include <sys/types.h>
" Y0 T2 ~1 P; R" j3 r/ O! r6 \) Q #include <sys/socket.h>
. P5 Z+ U1 v) u& `! E" B 函数原型:3 R, ]1 y. w4 a' K2 y4 s+ r
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
; X) ^3 B* E$ P$ c6 e, L sockfd: 目的服务器的socket描述符1 A4 E" i3 }" p' z
serv_addr:包含目的机器ip地址和端口号的指针8 V$ j( G+ \& y# r
addrlen:sizeof(struct sockaddr)6 ]% Y. k3 [7 m* i
3 I& o% U$ D( p# O6 ~
4 listen(); w6 ?9 Y* E. V1 C4 u
头文件:- b% o- z; O _2 a3 h
#include <sys/socket.h>* ~- g2 t# U7 S+ Q* Q3 N
函数原型:# f" o% D/ V! ]0 {- h
int listen(int sockfd, int backlog);" O5 k( o0 b5 d/ u/ r- v
sockfd:socket()系统调用返回的socket描述符
+ q- b* U7 T% j; w backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。: k6 P$ w: K5 g! \; t! _) y; H
+ R4 g4 Q; q( b, t/ p8 i2 n
5 accept()1 ]6 `6 F( P9 `# J8 T
头文件:
& G' ~! \. q. g v) M2 }( o7 E8 m #include <sys/types.h>
6 D+ q P- O! r3 }- }. E #inlcude <sys/socket.h>8 M! l' b) o; F) L7 o
函数原型:
2 U) _# [& C9 W' q/ @- B- | int accept(int sockfd, void *addr, int addrlen)
+ C/ ~( j9 |- O) J( v" \/ n/ v sockfd:是被监听的socket描述符
: _+ V7 R( W. h: e3 Y g addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息4 K6 L" f( y3 m0 o: P- B% O
addrlen:sizeof(struct sockaddr_in)8 b. A- A" `1 d0 u' \! J
' `$ S d7 x" c: {
6 send(). Z9 I* D% H, G% M6 ~) P
头文件:* T+ D( g3 w0 Q Y
#include <sys/socket.h>
) q: S# X0 V7 s) A1 F! B) z8 G* l 函数原型:
/ a( }5 D& {8 e6 B) D int send(int sockfd, const void *msg, int len, int flags);( A# }9 F6 S/ g6 q. y
sockfd:用来传输数据的socket描述符
) i, @* v; E% f7 y5 ?1 b: o2 v& T, F msg:要发送数据的指针 - @: Y* Q) s! n( h
flags: 0( U, P: T1 A; }( p
: i; t) {' Z2 v6 w6 i0 s
7 recv()" `8 J/ i' |* G, K
头文件:- i6 m- a8 C6 h( ^# o
#include <sys/types.h>
2 m/ B1 w- j% N; ^% [+ L- ~4 Q$ f #include <sys/socket.h>
( z6 Y- _ F: F+ V" \3 [; z: p 函数原型:
( w6 A: C2 K" S3 r/ Q: g3 C int recv(int sockfd, void *buf, int len, unsigned int flags)
" C9 X( F+ y" e% u R% X* F" F sockfd:接收数据的socket描述符
1 V0 H2 f) R8 o9 { buf:存放数据的缓冲区" P' B' J s' P9 L7 o1 ^1 |
len:缓冲的长度/ p$ a; o- n& z1 `+ }! D: ~
flags:0
2 y" i" o8 g3 E, R2 c" G4 K+ l6 \% S3 m, F& A6 E- U. H+ W! s6 ~8 |- D
8 sendto()
. ?8 \- ]+ J2 i C4 y 头文件:
( J+ [, x& z! S4 u" D K8 \ #include <sys/types.h>. y8 \9 z5 {) r, ~) W8 _
#include <sys/socket.h>- ?" Q0 B; V) L+ T' X/ X0 C
函数原型:
/ P( Q' ]0 i+ S( w int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
3 [+ H$ z7 O4 @( @+ J5 a) G2 [
' M8 o9 @% a z- u7 W0 F( n3 y 6 x9 D+ A( X9 G$ E
9 recvfrom()
0 i3 t- Z1 O6 |3 H4 K 头文件:, x1 z: W* z" D# g/ I* H4 \
#include <sys/types.h>8 W; }* D* k3 Q& U" R
#include <sys/socket.h>0 m' t, x" ^# W Q; W
函数原型:: i1 o% J% c6 }0 l
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)
1 N+ e* `. z3 T# n% K$ f, ]9 b$ c
% T" i/ x5 }$ L0 u2 \1 q. v
10 read() write()
1 |9 S8 x5 n5 ~2 X- m0 n( C- |; Z, P2 D int read(int fd, char *buf, int len)! Q! H2 c) I+ ~ v
int write(int fd, char *buf, int len)
) f* E& i: \, [6 e 6 F# ^5 u5 M9 M2 }' k( S
11 shutdown(): u) T5 I* N3 W. }0 `3 N8 R6 Y5 y. D
close(sockfd)3 F0 f- a3 Q* j8 |5 R
int shutdown(int sockfd, int how)
0 e& {* Z* G) I! Y) f+ K. ~----------------------------------- [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. J: N7 y% c$ M5 [. [' ?, r<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等% i8 I0 f( p# p4 P- R/ Q
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()6 s" U7 W4 W* O. [ v
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
2 [/ J* d+ L0 P4 z<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等- n- e9 ]4 c& R0 f% [
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等6 a4 y. ]+ o" _ T4 i+ S2 ^; K _
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件5 W# a& V0 \! Z# N6 i5 u/ R
* ^: X- ^ p/ v& w
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
/ |; q0 W9 @) r+ y8 P#include <sys/types.h> 5 \' [. v N* F$ q- p/ ?
! @7 u- X$ t( M' V
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
$ J" ~5 ^" g2 g1 I: d: x#include <poll.h> //poll,pollfd
4 q- {6 U" Q0 ^% ~#include <arpa/inet.h> //inet_addr,inet_aton7 n9 l' k% }6 V) A5 F
#include <unistd.h> //read,write
4 T, B; O( C. e#include <netdb.h> //gethostbyname
: x0 J9 Q1 [2 `7 V$ Z+ d; {4 ?' Z: q
4 J: H/ ^' t* `# o- `% ^* @5 B/ k#include <error.h> //perror, E1 V" ~* X4 H/ {, F% @# R$ b
#include <stdio.h>+ H+ l5 q+ z5 D" ]: ^/ l# R; @
#include <errno.h> //errno
: g0 K( x# @+ d& o
( k4 P: ~# c% g( G$ n* h4 y- V& Z& ~#include <string.h> // memset* B( E* A$ Z) d% m. \
#include <string>
' h# e( B6 L1 @9 |0 X#include <iostream>
( K5 Q* L; ?0 m1 l; _
8 |4 d& J8 E; B7 r |