[size=13.3333px]一 三种类型的套接字:
9 \+ N. o3 ^" q2 S* x$ B3 i$ p1.流式套接字(SOCKET_STREAM)* R( b: q+ {6 [
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。 V+ h% I9 H$ E, l' T I
2.数据报式套接字(SOCKET_DGRAM)( S, L: n x, s: {
提供无连接的数据传输服务,不保证可靠性。) @% m2 `, S4 j6 b1 ?9 y2 S5 z' I5 @; d
3.原始式套接字(SOCKET_RAW)5 A: |) ^/ s& `3 V! e$ }& [# N: p
该接口允许对较低层次协议,如IP,ICMP直接访问。
$ D$ ] L) Z- j0 G% `/ M ^& }5 T1 y* b( t/ o% ^. x) C' B, C
二 基本套接字系统调有有如下一些:
: v& D0 i- D9 x1 e: |9 G 创建套接字: socket()
' V+ [$ u6 |9 Y1 W3 k8 u: y' t }1 L 绑定本机端口: bind()7 p9 O* M: E/ j( Q/ |& Z
建立连接: connect(),accept()
$ O+ S& @) N5 a4 W" U! [ 侦听端口: listen()
4 u, ]- s" X/ V" ]0 {/ J 数据传输: send(), recv()5 T) [! k& ^/ ^% {4 a4 d+ m
输入/输出多路复用: select()
5 e2 r5 k p, e4 O% @2 l$ } 关闭套接只: closesocket()
. h9 x* {+ U3 V2 K
5 i9 G5 C3 V$ G% x1 G三 数据类型- U! a, P! ^9 U- c$ K& P
struct sockaddr3 t, ~7 J5 V; d8 [+ T
{
. \5 r2 \! @8 G0 J" }4 d u' y unsigned short sa_family; //地址族, 一般为AF_INET
1 E; D( l5 F/ ~) X3 q/ | char sa_data[14]; //14字节的协议地址' W7 n! b! U3 j/ ^! r# j- I
}; [ {/ N; |+ i
0 v( h7 n3 e5 W/ d: L4 W B struct sockaddr_in
" L( H/ E5 J# s0 u0 y {- ~6 J4 @& a6 K0 a; V+ `7 B* F
short int sin_family; //地址族
% b) @; Y' ~' [2 Z# a- X. G7 L unsigned short int sin_port; //端口号# }3 Q8 _& f4 C" c: R' a* Z
struct in_addr in_addr; //ip地址
5 }" E$ V4 m; p" ]7 s$ n5 ^8 O unsigned char sin_zero[8]; //填充* p7 w, j# k, E
}
7 j9 o5 q9 u9 `4 U, i# |* u6 g, a4 S1 i# V3 ^( A
四 常用函数
! [$ [: x% C/ p# x0 k 1 socket()
* L& @; k( U. ~) m) O 头文件: 9 t. h$ n5 W/ @% x$ b0 h/ E. e% T! t; I
#include <sys/types.h>3 z& D" k9 N6 s" w/ O
#include <sys/socket.h>9 D0 H& T6 P( q4 w1 T
函数原型:
5 J$ {% {: g' @ i$ ~ int socket(int domain, int type, int protocol)
6 o' D1 V& ^( Y domain: 协议类型,一般为AF_INET
0 T. c q, u- u- Y; H% C type: socket类型9 [: g( N9 I* w" Y. z! }
protocol:用来指定socket所使用的传输协议编号,通常设为0即可
4 N; T! P& z4 {5 i; a8 x0 t' x$ J* ?4 j3 u: K! v
2 bind()
+ K* J. \/ s$ |% q 头文件:5 {1 ?% f6 e! F+ k
#include <sys/types.h># @! {$ B& ?' v q/ s/ D; D
#include <sys/socket.h>! e M# S8 n) f( ?( _8 j
函数原型:
# C" C! Z1 ]0 @! `6 P K int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
^' I l$ o! K' n4 L sockfd: socket描述符
4 Q9 ?6 B' c0 A# j/ r my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
. U9 V# K) w! \/ D% Q# P- J( i addrlen:常被设为sizeof(struct sockaddr)7 b: L& W5 Y# o0 I
- ?0 y7 q: ^( L- F$ t
3 connect()3 U1 X# Z: H/ Z r
头文件:4 ^3 [ {6 I( b9 b$ z
#include <sys/types.h>
4 V t: ~7 C' \, p& [+ w2 ` #include <sys/socket.h>
) c- t: Y5 ^0 \0 [( X" E 函数原型:
5 r' f F* k v) @/ o2 L int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)1 d6 |; `8 E( I3 X
sockfd: 目的服务器的socket描述符
/ U3 _ Y# q+ }( z$ }3 | L& Z q serv_addr:包含目的机器ip地址和端口号的指针- G# _7 y, @/ g; s
addrlen:sizeof(struct sockaddr); O4 `& ]. V7 S$ }% r" j
/ p1 _! ^! p8 C5 \7 j' S& t
4 listen() h! }0 W* B* Z1 L/ ?$ Q) J
头文件:
2 U$ j* a1 k* y- c #include <sys/socket.h>$ W2 c) U% b: c9 F& x
函数原型:
6 `( K( k; N3 ~( Y! w: Z. s9 n int listen(int sockfd, int backlog);, {* Y9 j6 ~5 V6 s) s& {; y
sockfd:socket()系统调用返回的socket描述符: o7 w/ F2 ]7 c8 R3 t' e- k
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。
& `/ ^7 ^' U/ _6 D8 i8 d8 p$ M0 E) n3 e8 }) l/ q$ @
5 accept()
6 O" g. e9 x0 s- W4 \. T+ p 头文件:
3 j. L- t1 Q- J3 R #include <sys/types.h>! B4 [, d+ T/ w; O( \
#inlcude <sys/socket.h>
5 i2 N5 O, l# D2 n7 A6 @ 函数原型:. O4 b, a' S- J3 k
int accept(int sockfd, void *addr, int addrlen)( K) [- }- c# q% v4 I7 W0 u7 @( A
sockfd:是被监听的socket描述符
$ B7 R7 c3 K) E. v addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息; @, W+ Y; `0 Z4 K: `" m
addrlen:sizeof(struct sockaddr_in)8 y" |& ?) A1 ?6 z/ _7 G; M
' F0 p M& N+ Y7 B( F 6 send()+ e$ j0 ?' r) R2 k
头文件:& j+ d1 t: j' q" m4 a) I
#include <sys/socket.h>+ I( A2 q; ^- V
函数原型:
" Z. `: t: B, g4 j7 @ int send(int sockfd, const void *msg, int len, int flags);. @2 M& D' Y( o& f' E* Z
sockfd:用来传输数据的socket描述符 s$ @% J5 T7 i2 V
msg:要发送数据的指针 ! N x; G1 x B
flags: 0" r8 [: N6 V. i0 f$ |) A
* o" D+ D3 Z( g 7 recv()
/ y, R% m. y3 t# n' K 头文件:5 L* q1 Q4 Z) f. v1 s2 m
#include <sys/types.h>
" A$ k: R) z6 T, F8 f #include <sys/socket.h> {2 S R3 u( `' D! F
函数原型:1 j1 h# p7 H7 |( a
int recv(int sockfd, void *buf, int len, unsigned int flags)
$ j( ~: j# p+ b/ N sockfd:接收数据的socket描述符
4 X5 \7 m9 J( d) M( x; @6 |& t buf:存放数据的缓冲区4 g' J. J" {9 E
len:缓冲的长度
' l4 w; `1 |4 j# w, R E flags:0
; W5 n' u6 I. ~9 R; o U3 B, f7 S# S, v
8 sendto()
6 K7 [8 r! S0 i5 d2 a9 p 头文件: z7 n8 i2 e( v
#include <sys/types.h>- o- `) M* Q, _) t* J
#include <sys/socket.h>7 w" B; h4 G3 J3 y
函数原型:
: U2 D5 W# c- H" { int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);8 ]' d# o# q. O" h3 q- X
+ } q4 E! Y2 o0 t, t
) Z7 k' {5 B! [; y7 Q! S( u 9 recvfrom()' {* U8 c) d9 u$ p& A
头文件:6 C& s+ y' U; \! h8 v1 d
#include <sys/types.h>
( u3 a" h' J3 W" O #include <sys/socket.h>2 |' y" l1 E: s" g
函数原型:% W; \" w: Y% N4 Q+ v
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)4 h+ e1 a$ C' \" n$ I7 L, m: K3 v6 n
9 @& a: T$ Y1 o x' H! }
5 \. h% \- ]6 n' ?5 R
10 read() write()" Q- A6 L: p& k! }
int read(int fd, char *buf, int len)) K3 ^( p' k8 e& S; n
int write(int fd, char *buf, int len)
9 x2 n9 @8 o0 k$ p
2 m8 F, X. o$ V( O 11 shutdown()
) E1 M3 a% m% J9 J8 d4 g close(sockfd)1 a* [ e3 }' S8 x( M% f+ J2 s
int shutdown(int sockfd, int how)+ H+ q7 g2 f/ \
----------------------------------- [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等) 0 J& A4 r3 ]2 s& Q4 B# `- c! @8 m
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
8 l S) f6 u4 h' n7 h<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
9 Z: V6 `* b& \3 d+ t: F( ~<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等( h$ ~' r, B4 ^5 z: s0 G2 ]
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等- l+ \/ t5 O- D5 I/ b
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等- j' R4 @" c. g! N j
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件/ Q0 x7 t- o& n/ X/ W
5 b* d5 w! d% C# n& ]' c0 b
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
' I( ^/ [/ z H3 Q$ ]#include <sys/types.h>
6 L( t0 \* Z# E! o. h0 U$ `( V! J
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons( `2 j2 u: m* j( `
#include <poll.h> //poll,pollfd
! K3 N" D0 @9 l/ o$ ^#include <arpa/inet.h> //inet_addr,inet_aton
* t* m |4 |+ ^' v#include <unistd.h> //read,write
7 ^6 ]: U2 x5 w' Y#include <netdb.h> //gethostbyname# z3 u; @8 @/ ^
! @ Z) M2 \7 x4 K' ] C) B
#include <error.h> //perror
, x) @5 H$ k# O# m#include <stdio.h>
; l' ^; V, d5 q8 a# u8 V#include <errno.h> //errno
* y# u) _, J& s1 Q& s+ v0 C9 {5 k# p7 Y" A$ t3 T8 [9 t
#include <string.h> // memset; |& f# s2 ~2 s7 s
#include <string>3 C0 M* s2 n9 o5 d, r
#include <iostream>' Z2 Q. j6 h: T; P0 L# J
( u; n; C7 Q: S% F' D7 {# H' G$ R4 ? |