|
[size=13.3333px]一 三种类型的套接字:
9 x& ?' t$ Z4 J1.流式套接字(SOCKET_STREAM)9 ?8 }1 @; S- q$ u2 K: S" S
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。5 o! R0 P8 v; R8 d" z
2.数据报式套接字(SOCKET_DGRAM)
' T; Y" A. R' n! ^+ z/ U2 n. @ 提供无连接的数据传输服务,不保证可靠性。! H6 S3 W4 \; u4 O. c1 j1 y+ Z; h
3.原始式套接字(SOCKET_RAW)
$ c7 [* O4 y x, W 该接口允许对较低层次协议,如IP,ICMP直接访问。1 ?( t6 N* I: r8 M5 m: W5 r- o! Y
5 a$ Q0 J% y( [# q5 M3 O3 h- M% L二 基本套接字系统调有有如下一些:" h) q/ ~- J, _: G" K& F: |
创建套接字: socket() Y# e6 s. Q7 L8 j% r
绑定本机端口: bind()
3 q; ^$ |) ~* R) d3 F 建立连接: connect(),accept()
, ^' b2 [% L' h6 n' B& ]7 ~2 ^- p 侦听端口: listen()
, q% j$ W' R3 K( f5 Z 数据传输: send(), recv()
$ A* O8 _; S, d0 K 输入/输出多路复用: select()3 y) D3 Z( k9 s
关闭套接只: closesocket()% p- |9 O" s% L
" D( k- J& }5 ~- o( i& Q
三 数据类型: a* \4 `* b8 J! m
struct sockaddr
& j0 [1 f/ d# Q# q {
+ W& h3 T* c6 R. E& U+ J unsigned short sa_family; //地址族, 一般为AF_INET
+ j. q6 |1 c: ~5 b! q% K5 i7 K H) n char sa_data[14]; //14字节的协议地址* T8 g8 W4 z- I- \% f* R
}' D4 b4 R' x$ i6 h0 }
/ }9 ` K' i. E7 o+ g- n
struct sockaddr_in; X2 v8 C: R; Q6 T7 G
{2 r; n# a% ?/ j, c# H7 T% ?
short int sin_family; //地址族
" j9 ^$ {3 h! p* d. {! t% Q( {) O9 w unsigned short int sin_port; //端口号
$ k5 e, u8 p& \* |& f6 H8 K struct in_addr in_addr; //ip地址. z$ w5 z4 t0 J& P& a r: d9 m
unsigned char sin_zero[8]; //填充- y, G; ?% {2 h& f- H' |
}6 C+ P" ^) h4 B" v$ _0 n$ `
8 \+ N6 D$ o! d: D
四 常用函数" U! r; C4 K) H% G
1 socket()2 D2 P ~2 U, F. b. ~/ g
头文件: 3 v7 k/ @. J, \9 S3 s/ `2 w) g
#include <sys/types.h>% I0 J# ^+ W8 X6 K- J
#include <sys/socket.h>: ]+ a# n- {9 N4 J) ^
函数原型:
5 r0 T- K7 a7 n, u3 L' B- a int socket(int domain, int type, int protocol)' A6 [8 I D( @! B
domain: 协议类型,一般为AF_INET6 a. B% p$ a- o3 Z/ T
type: socket类型
; \. o; T# R5 h- Z' G protocol:用来指定socket所使用的传输协议编号,通常设为0即可% L6 p- V2 S; \2 _! D: V, Y C
" N3 D. ~7 x: j8 J3 s3 i) g
2 bind()
k8 @5 k5 N0 j6 f 头文件:
' n5 q% S8 A+ L; j& K! e #include <sys/types.h>
. y% j# T- R% i. ~9 J2 j" E# j #include <sys/socket.h>0 j9 [, r5 y7 \* h% @; B
函数原型:
1 A7 N9 d* p0 ` P: c3 i int bind(int sockfd, struct sockaddr *my_addr, int addrlen)8 _) Z1 I$ D* v( t5 ^5 r
sockfd: socket描述符
3 C2 e0 q0 D2 C& }4 _8 ?/ w my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
. e; Q7 k( m% r* G) j( W: X) ~ addrlen:常被设为sizeof(struct sockaddr)( `$ g- }7 Z# P! n V
( s7 E: v# i- {% ` 3 connect()
9 A2 i1 j$ D& L P 头文件:# z5 J T# H/ S2 D' ?
#include <sys/types.h> 0 H, A) J# }) H( V: w
#include <sys/socket.h>. }6 F5 `8 P" ?( |# j
函数原型:
$ v4 ^& m* _, ^: ~ int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
+ J6 z/ [7 S$ m8 z! t- @0 Y3 N sockfd: 目的服务器的socket描述符+ B% g3 G# }* h3 M5 i: W
serv_addr:包含目的机器ip地址和端口号的指针) d7 n0 N. [! p+ |( k
addrlen:sizeof(struct sockaddr)
+ v4 Z9 w! f2 n' G4 q4 r9 U+ I
; _+ h, e% F8 I; D 4 listen()3 {1 c! \( F- d: t4 k
头文件:/ Q' F1 k+ V! X. X# V
#include <sys/socket.h>
! Q. B. _+ u& @7 i2 f( F5 H 函数原型:
" A+ p- V& s: z- f; m int listen(int sockfd, int backlog);+ \) H, z" v6 I% G0 ^
sockfd:socket()系统调用返回的socket描述符
# {- a- Q- k' } backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。
/ F6 X, N' B7 ?$ Q6 T
4 L3 W6 h! _+ Y! R 5 accept()4 d: ^: ~9 F$ @2 o8 }- j
头文件:
2 L! G) v* X6 D; C) b1 ~% h* t& p #include <sys/types.h>
; i+ ]: t0 h' A) ^/ f3 O% ~2 ~0 c #inlcude <sys/socket.h>
# \4 F0 X# S- h& f: R8 ~1 S7 p$ K) I 函数原型:
. D, M4 u1 I8 Y! \9 i+ ^4 H# g. ] int accept(int sockfd, void *addr, int addrlen)
7 w: c; U7 K+ E* n o" w sockfd:是被监听的socket描述符
' f3 a5 @- b: t4 t5 J. _: K: ~/ k+ I addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
: G! j `/ t: A% i. j9 g/ R: \$ C addrlen:sizeof(struct sockaddr_in): U) I0 d. [$ q2 @
+ z! @* p# b* t' n: o 6 send()5 ~" v; t$ G, W4 Y! A/ K* l
头文件:
1 X( b' N0 B) P #include <sys/socket.h>5 U0 Y) o, J8 E
函数原型:/ J1 N2 C0 J1 j; E0 c
int send(int sockfd, const void *msg, int len, int flags);
4 Z( I, }! h% b+ r sockfd:用来传输数据的socket描述符
) b. R1 R+ L( K' o/ C msg:要发送数据的指针 9 f# ~6 Q8 K: {
flags: 05 r/ O/ p! M$ M% r
% i# C; m- s. z, e 7 recv()
6 M' i- w# t; L/ Q5 ]' T 头文件:
1 ]$ f {" J+ V- m; v0 ~ p) k #include <sys/types.h>
) ]5 E. F8 s* p. e #include <sys/socket.h>+ f: X1 X- f# |1 M9 l J
函数原型: `# m* b- `5 R4 Q4 A% Q
int recv(int sockfd, void *buf, int len, unsigned int flags)" f8 L( ?$ d2 q$ N$ R3 a4 s
sockfd:接收数据的socket描述符1 G" M$ h6 F5 g
buf:存放数据的缓冲区
9 A- r/ e+ U4 h) w len:缓冲的长度5 J' F, |$ T& O6 B6 U+ {, s" r7 O
flags:07 M7 w4 H2 ^6 s2 S* Q& D( `0 h
; L; w: ?* q7 W+ s7 T6 V9 y 8 sendto()
# }4 B9 b$ z% N2 s/ I 头文件:
: U7 _6 H/ o' u8 d1 e #include <sys/types.h>: Q; X) \. [+ C4 A
#include <sys/socket.h>
" o" _8 o8 X3 w/ s' m) q 函数原型:
( p( C3 f( x/ B4 W8 _ int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
9 K: ^" [, @& _" O$ h, P& D ) z" u: b- m5 K2 A" ~) ?4 |' P: j
x% x/ H V B+ F3 X/ E 9 recvfrom()( U" _/ W* t. ^' `4 A5 S
头文件:
+ G5 W1 |6 u8 y/ G #include <sys/types.h>, f; P! e/ F- S& x; i
#include <sys/socket.h>& z" G" r/ Y$ t/ h5 N! i# n
函数原型: T2 i( a/ O& s6 R9 [7 ?; ` Z& c# w
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)8 E6 L( c/ u2 c5 L! e9 j
; o4 j5 `* Z) p1 L " I6 u( B* E3 ]; e$ a$ w6 U
10 read() write()8 x$ {. j6 `/ i( K
int read(int fd, char *buf, int len)
% H" p2 B6 m8 _7 w) m6 {( t int write(int fd, char *buf, int len)
9 r" X+ F% b+ e: E2 L- f; f. l
, A) r! L, k; ?, d3 r; y* B 11 shutdown()
0 X; h8 i) _4 Y% t6 s! R close(sockfd)% F8 h& o6 R& n7 u& e
int shutdown(int sockfd, int how)6 f0 v5 q) |; p- [/ a4 f0 j
----------------------------------- [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等) 9 G! g3 A+ A" {6 n( |" m/ \
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等; f( P p* F* E$ R0 j# [
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
& E* N. H3 G4 b! l- F% D P<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等" F. ?1 g4 ?4 F' b) D9 k% M
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等; o9 ~" ]" e9 k4 P3 C
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等# ?9 G H+ f1 P$ t2 j" U
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件& @ P0 q2 h* K6 e
. W& M0 ?1 h) d \7 }* q
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等/ Q O2 E# U m _
#include <sys/types.h>
& h1 M1 L# [. }: B. s; G3 v# Q- i* n$ |# s |
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons; U7 p8 D2 w7 P% x
#include <poll.h> //poll,pollfd4 W( O7 G4 k3 j2 o# A
#include <arpa/inet.h> //inet_addr,inet_aton: n, N4 C& R$ n! r1 ~) E
#include <unistd.h> //read,write8 ?7 d% h& N2 D
#include <netdb.h> //gethostbyname
: ~% j1 a% L0 D. D5 G/ u6 a# a$ g7 L4 @% [; Y- M X
#include <error.h> //perror2 |! Y+ B1 p5 B7 w2 N, u
#include <stdio.h>
4 B) {5 |) ~$ J1 |#include <errno.h> //errno
$ R9 w( A6 y' Y2 E7 V' o. h" b1 D9 k( h- j8 Q; Q* M( d* b
#include <string.h> // memset
: U9 i$ P) }* c5 B1 y#include <string>% g: a! ^7 f( ]/ z1 N4 f+ a& w
#include <iostream>
+ k% O4 ^! l, u' B5 D: f& n# h/ [% A! Y' V: k6 l, `. L5 q/ V
|