|
[size=13.3333px]一 三种类型的套接字:# a" e2 T, V7 u2 |- Q
1.流式套接字(SOCKET_STREAM)
1 o7 P# P+ }! c/ i8 w 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
; M6 o; Y k1 ?# z' D& K2.数据报式套接字(SOCKET_DGRAM) C+ X' T+ b+ j
提供无连接的数据传输服务,不保证可靠性。9 J, X d9 C! k* D3 u3 l9 y
3.原始式套接字(SOCKET_RAW)4 p4 i# M9 \; e# j
该接口允许对较低层次协议,如IP,ICMP直接访问。
8 i( y5 P& g e/ t) V! G7 m0 E/ C" x' c9 l
二 基本套接字系统调有有如下一些:( V( K0 x x1 f, ]) `- t% @) m
创建套接字: socket()/ j# t' b2 D2 T; `- V) h
绑定本机端口: bind()
/ Y; j; r6 | ^. M: g 建立连接: connect(),accept(). O& @4 w$ u, Y$ t
侦听端口: listen()
9 L- u( H6 m9 k0 ^7 S+ h8 c" n: a: { 数据传输: send(), recv()
# r8 Q: L) O' [3 S; o 输入/输出多路复用: select()
5 e/ U& b. X; D% f6 U) G 关闭套接只: closesocket()
, i; _6 Y" o G$ o6 S* t
8 r O) n- t* M w三 数据类型, ?3 \ l* W4 N5 B0 r& z$ U
struct sockaddr; u" V( c" \# y
{
+ d+ a# ?' b! t' D unsigned short sa_family; //地址族, 一般为AF_INET4 Q4 @ a2 b* l& H) f: e% T
char sa_data[14]; //14字节的协议地址5 I/ j. a8 ~" K
}
0 V. S2 L8 f' J/ ~2 h' j, x( h
# O* K5 ^: d6 J0 e struct sockaddr_in
% \, y7 }- L0 {0 s {
" x: [1 m* I6 c9 ~2 r. k9 \9 F; z short int sin_family; //地址族
/ r1 a- x1 I8 r& }4 M* k- |; G# Q unsigned short int sin_port; //端口号
+ _! c( H# f5 o; e+ Y( K struct in_addr in_addr; //ip地址
" [) z2 }0 O% \$ t5 U/ s& ^! a! j& ` unsigned char sin_zero[8]; //填充2 Z5 v/ m1 C0 w! c! ]' H* Y
}5 S. q$ n. H8 H; i
) j" k7 X7 S; x
四 常用函数
@! f4 T5 S f, M 1 socket()
& [; }/ V* e( }7 L# H# P: y 头文件:
! f$ q* d& I$ R' n #include <sys/types.h>
; r o, R; O% b2 a8 M: D' ? #include <sys/socket.h>
9 _9 K2 s1 W0 l$ b- x. s v 函数原型:
2 P) i1 H. }7 c% b% @% X3 @ int socket(int domain, int type, int protocol)
/ R8 A$ }! E& |' K- Z# \ domain: 协议类型,一般为AF_INET/ Q1 k5 v8 p, j9 s& u
type: socket类型
, T7 U- {+ w, ]4 e# S protocol:用来指定socket所使用的传输协议编号,通常设为0即可
0 j/ O( {" m0 n @9 N X5 R$ J
, R5 R5 @" n- _ 2 bind() i7 l$ v* S2 I2 C2 n2 T0 X
头文件:9 i& F* P7 [9 w1 i
#include <sys/types.h>$ i2 ~8 t$ w% ]/ O+ q( \
#include <sys/socket.h>
, g3 C7 `$ [% _. v v8 N; M 函数原型:
9 x) r* }6 q! u0 {1 s int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
; C$ `- t* F, _/ Z sockfd: socket描述符
1 n, J8 G: f; L8 m my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针5 H$ g7 D; O) i, i
addrlen:常被设为sizeof(struct sockaddr)
+ z2 m' }% k- O2 f# D9 a2 \% Z
3 a. \% L1 L9 A' p( f 3 connect()
9 B4 D3 y& C+ r$ |8 m1 s( f 头文件:0 Z0 w% V+ y6 Y# s- _ }
#include <sys/types.h>
! v) D( H3 e6 e: g0 \' e; V #include <sys/socket.h>+ e- H( Z7 O! P0 I2 \
函数原型:( o: }/ A1 Z+ X0 b0 y5 f
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)! i! l& ^9 v( q* L9 e! k/ y, A& h
sockfd: 目的服务器的socket描述符7 p. I% Z# T7 G0 V
serv_addr:包含目的机器ip地址和端口号的指针7 L. @2 f8 |6 O3 \
addrlen:sizeof(struct sockaddr)
0 f' ~, Y$ u* e+ k _% F* S& H5 J0 L( y7 _
4 listen()7 N3 N% j$ Q& ?8 b6 u: w: v
头文件:) F3 C, `/ W/ ~% ]) K8 f; c
#include <sys/socket.h>: ~5 {7 s2 Q6 ` H/ n0 N, `
函数原型:5 B& Y1 Z; I/ E" R4 S) J' I E) F
int listen(int sockfd, int backlog);! h! I$ l+ u+ M7 ?/ w$ ?- \" _
sockfd:socket()系统调用返回的socket描述符2 L% w: y9 c& r/ D$ L
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。2 l$ b2 E T! r; Y9 o
8 n! _! d; J; W i' [& q
5 accept()' w; t6 X- t- E" D, ]0 d$ N5 I
头文件: 5 `5 i6 v" W4 @- j6 R+ s6 A
#include <sys/types.h>
) i2 v! g B' b% D; {1 a #inlcude <sys/socket.h>
8 U+ L+ R" Y- w. i5 n7 k+ {( r 函数原型:8 e9 U3 S& [, j$ W/ ^/ s
int accept(int sockfd, void *addr, int addrlen)
' N" t( M9 Q9 C4 b sockfd:是被监听的socket描述符% J( T. G$ X6 a) J. E
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
+ e1 Q; J) S0 U0 L addrlen:sizeof(struct sockaddr_in)
* k6 ]. j1 }5 I0 K
4 ~3 ]" k# ^; L. {9 V, l9 U/ y 6 send()
# [/ C. f( \8 C 头文件:9 q! i: m( n" {
#include <sys/socket.h>2 F7 |9 O( C) J5 V4 ~& g% ]
函数原型:
0 S( q9 k. l7 D0 X1 ~9 \; q int send(int sockfd, const void *msg, int len, int flags);/ k! I! Z% q$ Z
sockfd:用来传输数据的socket描述符) j) X* a, R2 f8 `
msg:要发送数据的指针
1 ~( F" }* j1 Q) w3 }) U Y flags: 0
, u0 p: b! |2 {3 ^0 J
# P" u8 J" B. H' H 7 recv()
$ Q: y. S& H7 W. Y6 |" u 头文件:( e% E! x8 X0 Q: T0 d0 j8 ]
#include <sys/types.h>
# Y3 u4 k. R6 ^6 x2 |4 c4 y #include <sys/socket.h>
% o$ g: L8 m+ v( a 函数原型:
% Z1 b9 q7 q C* ], } int recv(int sockfd, void *buf, int len, unsigned int flags)/ |! l5 u. Z* W. V
sockfd:接收数据的socket描述符
: \! Q0 E% {0 V& p) H buf:存放数据的缓冲区
! n6 ~5 }9 L0 v len:缓冲的长度7 X1 g$ B' P4 n$ |; {& O! ^
flags:0; A) \2 N- d. K) K2 X+ W, Q
" D; l0 ~+ T* a* @ | 8 sendto()
' @" ~" P% |3 w' M v. I( m8 v) A% H9 g 头文件:
! h7 _. ]5 I% l8 E #include <sys/types.h>3 n! E4 b3 c& `& C
#include <sys/socket.h>
, _8 B" v8 z* V; m( ]7 v 函数原型:
/ q2 \! t4 b9 r1 ` int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
. k; _* l7 F$ r; B8 A : B( R# k+ `# x3 U8 b
7 y O' u& U* _. w/ V6 W% f 9 recvfrom()
: C5 n+ _/ w/ L" w" W 头文件:* G# p6 h$ n* A" m$ g2 D X2 L
#include <sys/types.h>
! A- @* j( v! s #include <sys/socket.h>
" b) G' X" D% w4 l 函数原型:
; E7 L! s3 x" p6 U3 M) Q0 P int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)
% W% L0 f9 T: f n) |5 v0 ^# ]6 k7 q0 j8 \7 b
) S1 i! V* a9 C# ~- j 10 read() write()
4 q& n( ^' `5 F# F: C2 c int read(int fd, char *buf, int len)2 D) \8 K3 d1 Q/ E3 {$ j
int write(int fd, char *buf, int len)
0 S3 i; a' [% G9 J/ n+ E2 f 4 f9 L5 @4 K; ~
11 shutdown()$ Z- d% e# l7 {7 W
close(sockfd)
2 t- B' w- t" f4 f! I. D& | int shutdown(int sockfd, int how)* q- m" M+ L7 j, v# }+ k) ^0 i
----------------------------------- [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等)
% C0 I& q# V' L; ~( J<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等+ f) D; ^! }( c
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
7 H0 d( g+ k* I% z6 m/ V<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
2 ?3 C; {7 B( R+ r( e( v* y$ u<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
2 D; y9 F! E% T) M& h. ^+ e: E<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等! ]6 Q! h+ w0 P9 @4 L1 z. O
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件4 w' l2 }% C ]. P
! D& E2 z7 ]; `% H
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
& E7 z# i1 h+ i$ A#include <sys/types.h>
. Q& u9 S" C7 e4 G4 e2 [5 D- `+ S* P' n. L5 u1 e* d
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
& X- C* ^" x; y7 V#include <poll.h> //poll,pollfd1 S" y3 [3 l0 K2 G8 O
#include <arpa/inet.h> //inet_addr,inet_aton; A2 a, R; Q2 T V
#include <unistd.h> //read,write
5 R6 J0 i6 V9 u: e+ }0 F% `, g#include <netdb.h> //gethostbyname
8 A& D$ j7 G7 h3 M# Y9 y1 D: }% K) x* } H( o
#include <error.h> //perror* _" u- ?' E2 N. @7 U& D( \
#include <stdio.h>; C1 S y" g, H9 E# f3 q- j
#include <errno.h> //errno
5 S" g- Z6 t( |" P$ L
. K) S/ L2 F0 z' m# j* {#include <string.h> // memset
1 N) |! |0 V" B8 M8 w#include <string>
* q* }' M& E) @: I5 B8 c#include <iostream>9 w* s8 O6 y, n; p* Y: D2 P* d2 [* b
7 V- d4 ?' E% F. X, v/ Y |