|
[size=13.3333px]一 三种类型的套接字:
+ Q0 n: }+ X) }2 w9 ^) V$ E0 ^; A1.流式套接字(SOCKET_STREAM)
/ }# x) S) v) a3 |1 V; z5 U0 } 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。" _3 }2 o/ O2 K5 Z& i
2.数据报式套接字(SOCKET_DGRAM)
8 _* a1 {6 z$ I& y; M8 d 提供无连接的数据传输服务,不保证可靠性。
- M; t$ O- L# g) \3.原始式套接字(SOCKET_RAW)6 {' Y) M. d$ ~2 p7 Q& V
该接口允许对较低层次协议,如IP,ICMP直接访问。
9 o+ H+ u8 L7 L- _
" H& a) q7 c) C- T7 Q二 基本套接字系统调有有如下一些:
u% L9 |" m ~$ P 创建套接字: socket()
! T Z7 A5 S* g/ n7 d 绑定本机端口: bind()
& G2 S* T; z7 g) [0 a 建立连接: connect(),accept()
; @7 @# o: B9 G0 y' C& C% ~ 侦听端口: listen(), |5 R% q0 o' {- j+ k' P+ s
数据传输: send(), recv()% j0 v+ i! J) f% P" B- b& h0 d
输入/输出多路复用: select()! e( m5 ]7 U! n( [
关闭套接只: closesocket()" O) h# h! @2 c% ^: z( m
; L# l) v5 b- e三 数据类型; K0 B8 l$ a! T) W6 u1 p3 \* d
struct sockaddr0 S) T$ G6 i4 Q( V
{
% z$ W: W q- Z5 k unsigned short sa_family; //地址族, 一般为AF_INET% }8 n" w- i- F2 h& U/ X) m% t
char sa_data[14]; //14字节的协议地址
% ?% j' v: }; q' E/ S- e# U }; ]- S ]) d) O: \0 F \0 _
. e; m2 a k% v$ [ struct sockaddr_in4 \9 a# F. h6 P( n" ?7 u, I# e
{
4 j9 X: o+ v, n1 X short int sin_family; //地址族
t5 u, H& ?! `$ k. D unsigned short int sin_port; //端口号7 I: I# s+ R; d- u
struct in_addr in_addr; //ip地址
, c% H+ ~/ Y. K8 }$ \ X! v unsigned char sin_zero[8]; //填充
. N$ o2 }* Y# |2 w, z" Z i% [ }
0 |5 q4 A; j4 M/ c, f3 _( B% m! e1 \ c. v5 {4 Z: b
四 常用函数& W$ l' S5 k( B! B6 a$ W7 n" o
1 socket()+ t0 W8 E. }* L
头文件: ! H8 O* O5 i5 i& n
#include <sys/types.h># j. F3 k1 v. i- E
#include <sys/socket.h> n2 x5 P# y# L4 g4 F. G
函数原型: G7 l, u$ p! v0 C4 N, D7 e" \
int socket(int domain, int type, int protocol)6 S, `& R4 j: A8 |6 P# o0 B
domain: 协议类型,一般为AF_INET
( y1 T ~$ U- K type: socket类型
Z, I6 v. d7 G% v. f" A" L% T protocol:用来指定socket所使用的传输协议编号,通常设为0即可- G1 g0 A3 c/ T; p5 D
8 l Q& u7 A: k/ k- {
2 bind()2 ^/ y4 p' i* U4 q
头文件:" ^6 A* o+ x3 B$ Z( W( f0 H
#include <sys/types.h># q, B, i: L {' U. g9 D
#include <sys/socket.h>1 |4 {/ p' @9 C' ~( w' e
函数原型:
$ v! A7 w1 ^" S# M' e# s int bind(int sockfd, struct sockaddr *my_addr, int addrlen)' ~( ^* a. H: l% w% C/ a/ J
sockfd: socket描述符
0 c& z T' G5 g, E) U my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
7 m9 V' W7 c* ?$ q& L+ j addrlen:常被设为sizeof(struct sockaddr); G. C6 x4 H. v* @
% L$ O+ |, r: H. q) o, E
3 connect()- l% K4 ?6 O& S
头文件:1 T2 b# D/ `, a$ d3 \7 u
#include <sys/types.h>
2 N& d- [/ A9 L) | #include <sys/socket.h># u3 q# [9 m; Q6 R0 c) x
函数原型:# C6 n7 p% Y$ S( q1 R: m& Z; f; E
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)) L" A- k K X7 a6 t3 w( r
sockfd: 目的服务器的socket描述符
" _9 R0 x' a' T7 H serv_addr:包含目的机器ip地址和端口号的指针
% E" [/ Z5 [; X! d. x* r; R; ] addrlen:sizeof(struct sockaddr)
& r7 g5 N- m5 ~2 @
: J/ ]2 u+ \3 L6 T 4 listen()3 m+ R- K: E8 p+ K' }% G, ]
头文件:
6 U3 k3 d h3 L, m #include <sys/socket.h>
, {, c. O- _( |* P! p, j 函数原型:
- Q" B# ~. n( m' T( L% y6 N int listen(int sockfd, int backlog);
+ N, i ~8 C3 k7 M2 J9 E* t sockfd:socket()系统调用返回的socket描述符
' q$ |6 ` z6 ?) ^ backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。$ a5 T+ h0 s. X9 b
5 q: H1 j' Z" x1 o
5 accept()
X& K' _ r ]7 P. B6 {4 D 头文件:
k- y$ w/ m* t+ Z: T5 m #include <sys/types.h>4 K2 s4 L7 \$ Z+ J, y1 o, y
#inlcude <sys/socket.h>
' {3 R! H. U+ P7 u: a h+ s! D 函数原型:
5 _) ~3 J% p E6 V6 P int accept(int sockfd, void *addr, int addrlen)$ C) \( p3 w1 O
sockfd:是被监听的socket描述符! M9 Q3 e4 X9 `- ]
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
3 u9 p! a& a1 R* u7 T addrlen:sizeof(struct sockaddr_in); k* S5 g6 m" a. a8 ?
0 F9 U) ~1 r% f* G
6 send()
' i* [ r& }! Y$ ^5 w6 N# p 头文件:& w4 U' o+ _+ c" e/ ^
#include <sys/socket.h>
u5 i, ?* i5 z. P w 函数原型:
- \9 g* ]+ V3 d7 i2 i0 O) } int send(int sockfd, const void *msg, int len, int flags);
4 m1 n1 n+ q$ H% d2 e/ _+ b% g sockfd:用来传输数据的socket描述符
, g7 E# W# I' T } msg:要发送数据的指针
2 f! |- k _: c1 R% G1 k. m flags: 0: z/ B5 n$ C6 @( \& j
# R" \5 H1 [6 h' J( `6 X, H+ y. `* M
7 recv()3 N# v( A+ p* J2 t$ z" e. r( K* K
头文件:
; w: n. d# c+ R' ^4 i" ]/ L" ` #include <sys/types.h> g! W0 z( ]* Q, C9 G1 h! t1 e
#include <sys/socket.h>
2 v' U O& m3 @! x 函数原型:
0 m4 d" [2 }( ^$ z) G# z int recv(int sockfd, void *buf, int len, unsigned int flags)
) l, T% |& K8 v9 e* @ sockfd:接收数据的socket描述符' ~' t3 {2 [$ B1 }
buf:存放数据的缓冲区3 }" q0 |7 M. I* u
len:缓冲的长度1 f. H" ]! S7 S
flags:06 l8 B7 A5 G, w* N4 I+ F/ D% E
E3 }0 T/ b* T+ S 8 sendto()( Y2 l! h* I: y( ^( O- U+ @$ S M5 z
头文件:
( b' Q! C \. d; X/ L- M #include <sys/types.h>
6 m! N# i3 R& |: O$ z1 j+ }* z+ ? #include <sys/socket.h>: L8 ]: @* Z' M) P& n
函数原型:" V3 @9 d; g' d. A$ S+ q; b: E
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);3 R9 m, {" r u* K
* o. T+ a6 i% g: @
. x* y4 ?, J6 J
9 recvfrom()
9 J. ` a4 |8 b: q 头文件:. O% a; X4 Z+ \
#include <sys/types.h>2 a" E( I6 k9 p$ s# a3 n
#include <sys/socket.h>
, \3 H' \" {$ D9 F( n 函数原型:, E* G8 ?/ j2 X! \5 L
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)9 x3 U% M% [$ l. m* `, F3 q
: r5 m0 b1 Z5 R
, o: @7 F/ ]& f* @# e 10 read() write()
& v N w, S! h" ]: c' G int read(int fd, char *buf, int len)
3 _( ]$ M3 a& F: |1 B' M1 f) ?+ U int write(int fd, char *buf, int len)% Q- j# S% A+ t
0 j9 h+ e# I( ]8 y5 G" ]
11 shutdown()( E7 ^$ r1 O- d1 E8 Y; u
close(sockfd)6 \( D, c+ q# k0 [( A
int shutdown(int sockfd, int how) A6 R4 d9 J2 G! u, |- Z
----------------------------------- [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等) ( ]: ?+ @- z' G9 ~( G$ v
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等! a; [$ ?( t" d7 \, N
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
$ t$ I0 a' H/ A0 T3 n% Y<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等- K# }7 l$ s c7 `
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等& A3 H' U! k3 F! S5 p3 V2 T, x
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等% N4 E% _( Z% h& u' I- A1 v
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件, [. c3 g% h* K& i0 }1 \' z5 _
# @( C+ Z: a6 g0 q2 c. a
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
' V! q$ Q8 O- }3 C" a/ ]0 @#include <sys/types.h>
# q7 b9 d+ H- g
1 x6 g Q; N; a# \" J9 l5 z3 D#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
' y8 G3 @' u0 D/ K$ I5 L#include <poll.h> //poll,pollfd
) a5 L; c: Y# K( E6 Y#include <arpa/inet.h> //inet_addr,inet_aton
' @8 `6 @ V1 [, P: {8 R/ K+ O$ F) M#include <unistd.h> //read,write
b. g" p5 h) u#include <netdb.h> //gethostbyname
7 H5 t! H/ R; ~/ ~7 k4 P7 i
! n+ n8 |$ ]* i# o3 ^" t5 {# Q#include <error.h> //perror' x( s' S- M2 |& T
#include <stdio.h>- N- F8 P9 c; b8 z0 {, g& {8 _7 x8 {9 ]) g
#include <errno.h> //errno
% S) }1 v- ~& o: w5 `$ J5 y5 |. H( {1 N. P+ D: T- X7 W
#include <string.h> // memset
' G' D% M3 n/ d! B#include <string>$ i) y, ^% Y3 h
#include <iostream>1 s9 Y- L* m" R
, Q% ]8 u0 t ~: P" T( I( b |