[size=13.3333px]一 三种类型的套接字:4 Y: n' d# N+ S5 x; v
1.流式套接字(SOCKET_STREAM)
. w* B1 ~# c. }/ I1 b1 k9 p, b 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
$ @( l- k7 q" s& w2.数据报式套接字(SOCKET_DGRAM)
0 E% F' m; B n: i$ v" Z& \ ` 提供无连接的数据传输服务,不保证可靠性。2 ^' I0 b, h6 `6 N
3.原始式套接字(SOCKET_RAW) P+ N- E7 o' z5 G1 q7 f$ c2 X; @& M* A% {% e
该接口允许对较低层次协议,如IP,ICMP直接访问。# \, B5 K# x3 e# h
. p9 f% a5 N3 g二 基本套接字系统调有有如下一些:9 O8 O& ^. P" T! J4 Z# Z7 ^
创建套接字: socket()
5 r" Q& W5 t' m5 o3 i 绑定本机端口: bind(); I/ Q/ S' v: G2 \6 E6 J/ L
建立连接: connect(),accept()
: u. V- X* p( z; I8 G1 m 侦听端口: listen()
+ V" Q8 `5 z4 ^) F$ r7 D 数据传输: send(), recv()
4 I* F' v3 d% J/ Z) J1 X n. D5 o 输入/输出多路复用: select()7 I" Y4 n# N" J) c
关闭套接只: closesocket()5 d3 v5 d$ e/ M3 T( D& D1 @4 l
# r3 ~+ t' [; j8 t% P
三 数据类型1 b: Q; t3 z9 A7 j& ^( g! L- ^
struct sockaddr
3 V% \3 d& c/ J# r) d5 l3 b {. f+ Y) I' |! B( F5 Y9 m, o
unsigned short sa_family; //地址族, 一般为AF_INET
2 Q0 P1 T) X4 p* t% n0 R5 ^ char sa_data[14]; //14字节的协议地址
* T3 p- p' V- R# D1 R( i }7 E' d; @9 h3 y7 O' Z+ m
3 q: _" ~( I/ O2 g struct sockaddr_in; n p' z0 p2 Q* j
{3 F' g* I P; H4 B$ D; }
short int sin_family; //地址族) X8 B2 L* W$ N2 N
unsigned short int sin_port; //端口号
5 R% C: V; m3 ?" H# b" H struct in_addr in_addr; //ip地址
0 s) @9 d& K# X. A/ u' H9 X unsigned char sin_zero[8]; //填充: D; t/ [3 h q; \ u7 [% S
}' y5 N" p+ a6 {; L, L8 @0 T
( ]) C, j/ N* {5 e7 w! R* K6 P四 常用函数( Q2 h, \% ^% I
1 socket()
/ Y& b5 I1 h5 I# z 头文件:
+ Q, |: R( Z) Q #include <sys/types.h>
' u* `1 {3 t$ F# \$ ?$ v0 o: p #include <sys/socket.h>
, o1 R& n; P6 d; ^& | 函数原型:. f2 V7 A* A$ F" p, L
int socket(int domain, int type, int protocol)
6 l5 O8 }: P. d+ E0 r5 ?+ D domain: 协议类型,一般为AF_INET& w6 j4 W* @5 U" O) ^' M* P
type: socket类型
* B: l! z3 H$ u# G protocol:用来指定socket所使用的传输协议编号,通常设为0即可
7 w' G* X* V0 J2 [% A0 s+ ^+ m, l/ s2 H0 d+ Z
2 bind()& g: m' t+ ~7 ?1 x1 m* x6 o$ o
头文件:6 U$ W, S' F& V+ }5 r
#include <sys/types.h>
! r3 s" J2 P5 \8 h+ U: }0 N #include <sys/socket.h> l+ u6 P( t( l: O
函数原型:& u- H4 f1 r. w; U0 m# O
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
' x, ]9 Z) y0 q0 Q' \- h( [$ J sockfd: socket描述符
. |; Y, j& S4 F% i% X1 [- w& ^: { my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针4 Z) M2 X5 R% }6 m$ ~ ^
addrlen:常被设为sizeof(struct sockaddr)
8 }3 E* H- y! ~8 x4 I1 h; q- V6 \1 \' a, F. n) c
3 connect()4 W% k# j) ^' I* W( e/ L4 E
头文件:& u0 D- w t' D9 C$ b
#include <sys/types.h> ( b7 z$ X! Y" E) q/ Y# `
#include <sys/socket.h>
6 J- N% R" g% s% o- `" A 函数原型:
, G; H1 N. z/ o int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)8 @& b% ]8 ~: G* Y+ m7 @; S
sockfd: 目的服务器的socket描述符
8 b' n) ?) \% e serv_addr:包含目的机器ip地址和端口号的指针
4 F( ~3 \7 h3 B2 L9 { addrlen:sizeof(struct sockaddr)
+ c5 v4 Q& d$ F: Q/ c' ~1 P8 d
$ t6 t5 v6 \6 |, L 4 listen()
9 H6 N# q/ U" q8 J& D$ i2 A7 m 头文件:% q H9 m: b! M9 I
#include <sys/socket.h>- n! {9 b: w4 ] b8 _) y
函数原型:9 z0 y l# h2 ?9 J9 k' l$ ~/ f
int listen(int sockfd, int backlog);
; p! c* F5 {# J; P/ O sockfd:socket()系统调用返回的socket描述符7 g8 T7 B6 D' f& T+ z) w
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。4 U& `+ C6 Y. r
r+ }; e( t+ b 5 accept()8 e7 N: ]0 v8 r& {" Z
头文件: # `7 X" r6 X2 M+ N( m! L) N6 v
#include <sys/types.h>! N" e, n9 f5 t; A
#inlcude <sys/socket.h>
r8 K& |3 M+ O) I3 ^+ A 函数原型:/ c) Y( \7 ?. d- ~' G: S
int accept(int sockfd, void *addr, int addrlen)
8 c" \- g9 X% A: h5 u6 Y( D sockfd:是被监听的socket描述符' K0 Q3 Y5 K* V) Q4 A, j# u
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息, i, u3 g0 M% X2 f: N4 \
addrlen:sizeof(struct sockaddr_in)+ q0 R% ^8 k# L& {1 e/ J
, S, a8 f$ Y& i; B3 b
6 send()- C! y+ V; q0 O2 A
头文件:
% B& o- e6 O1 v2 R #include <sys/socket.h>
: w" X: O; o; [4 _ 函数原型:( b) v. I' G# Z, ? O- f3 r! e
int send(int sockfd, const void *msg, int len, int flags);
5 v- u2 H) g2 J S' s sockfd:用来传输数据的socket描述符# ?$ C2 S8 Y6 G$ Z& N
msg:要发送数据的指针
! z7 L; ^6 J1 \ flags: 0
: K. p) z" B9 D0 z: u) | - l- G$ Z+ ~5 i4 G- I9 E
7 recv()6 Q% {3 P$ c; N# c
头文件:- F9 g+ W, ^3 B* D `. K; s) F
#include <sys/types.h>5 z% _: _3 p4 @
#include <sys/socket.h>% c& o: t: `; n! ^$ @
函数原型:
# S) V. d; ?2 P$ {5 ^ int recv(int sockfd, void *buf, int len, unsigned int flags)
1 n0 K( y" @3 i% b0 j" ~ sockfd:接收数据的socket描述符2 L- D; l, M( n& L
buf:存放数据的缓冲区: c9 @; O! b+ _" n4 y' ^' o6 ?
len:缓冲的长度; }* s- z+ u5 s; |
flags:0
' [; A# d+ |% s7 \) \4 B4 r3 X8 K! O; l9 i4 e" M, J
8 sendto()
* G: A: P& O4 N4 v( w- w 头文件:
0 I$ i A1 O2 N/ t) ] #include <sys/types.h>
% Y, W( G5 X" N0 } #include <sys/socket.h>$ K0 f8 _0 s3 Q$ g) ~. a
函数原型:: c! E' V3 [/ h# X& n
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
5 h- d) N9 b. i/ M+ R2 F! u0 G, S
# g. `! J; ?: V. D: r" B: ?* D4 R
% S1 A2 k8 l8 x0 | 9 recvfrom()
7 r5 w9 `3 X) U9 _5 J$ v 头文件:( B& {" ~* r( b9 z7 g! g
#include <sys/types.h>) J* ~& D. K$ ]" o% }
#include <sys/socket.h>
( d8 f6 M, i- P! l5 F 函数原型:3 r! Q" a4 X% s9 B. r
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)
: P' |$ M# ~, _4 B. V; Y3 V3 }# q$ R" c1 ~ `/ K
5 V1 ?7 q4 [; d$ N9 ?" f
10 read() write()
, e% k' W5 W$ L+ N+ q+ a int read(int fd, char *buf, int len); J% e& d( a( N4 \$ \) k ^5 n- K
int write(int fd, char *buf, int len)
# U, @3 n4 x: a7 H c 0 \. F4 \* x. d' q7 _
11 shutdown(), f) |8 ~% m: L9 ~/ _
close(sockfd)! s8 W, }1 D# B, w- a3 S; \/ Z+ w2 L
int shutdown(int sockfd, int how)1 r; S4 L# B6 c% R
----------------------------------- [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等) 7 ~& i! T, v3 I' ?, A
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
8 T# W+ @9 l) v<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()9 k, Y8 ]) I2 I, P
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等# g# ] F) N" h+ K, u! m8 s% r
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
( n$ f, K! |; V; V& G( F<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等3 [* S% v' z2 \7 {& B
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件
% i0 T$ _7 e( F" Y' d. j: N
2 b8 v3 Q+ v+ t5 v+ h5 @[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
; r- o' w5 E0 A$ |#include <sys/types.h>
4 O7 h# \! T! i5 n1 |5 A! e6 o- H' d9 p' K8 P
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
( L3 N' i q8 N3 v#include <poll.h> //poll,pollfd
5 D2 E) c: p: w& Z) I9 e#include <arpa/inet.h> //inet_addr,inet_aton
9 R" B1 M" [0 e) Z#include <unistd.h> //read,write5 V& d, T) b" ]$ x- @
#include <netdb.h> //gethostbyname ?1 Y* ^ p' S p* C+ k
) }' K/ ?% \6 A: \2 ?4 g! D#include <error.h> //perror% T3 w# H( A' v' C
#include <stdio.h>
; }! g O2 Y- e) X- }. ~+ u. ]& Y#include <errno.h> //errno: w; @$ T8 h# j
: w0 S/ a8 c6 r
#include <string.h> // memset
+ G0 p- O; d& X: s q# }5 D#include <string>
) J8 S) a( W8 d#include <iostream>: X, b+ R/ ~& X) L: W
4 |' L% o: w& {/ n6 X |