[size=13.3333px]一 三种类型的套接字:
8 Z: y% f8 E' f/ N+ ~ G1.流式套接字(SOCKET_STREAM)* x) g) L) ^; I
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
7 F% P7 \- _" H- u: _2.数据报式套接字(SOCKET_DGRAM)$ H/ V6 r! m6 g7 u4 p& `
提供无连接的数据传输服务,不保证可靠性。: ~: Y: f* i$ o2 D, W6 k+ Z" \
3.原始式套接字(SOCKET_RAW)
, K$ q- \. q: J* O 该接口允许对较低层次协议,如IP,ICMP直接访问。, S* L! _- j7 N8 S) t4 X O% D8 k( o
E& n8 U5 ^- Z# ?
二 基本套接字系统调有有如下一些:% T/ {- `5 l3 }& o$ O! S
创建套接字: socket()7 M0 Q8 n5 U( F' w
绑定本机端口: bind()
' [" d" g* Z( W! F4 K 建立连接: connect(),accept()" H, \7 L3 C. r+ c# h3 E
侦听端口: listen()
& w* }8 ^5 j) a2 L, p4 v { 数据传输: send(), recv()! I( b4 v2 k& ?: z" P7 m( R- y
输入/输出多路复用: select()
" l6 X" V2 }. t8 x& y( B 关闭套接只: closesocket(), M/ I/ X- z# N: K7 P2 D
* Q% ]# c& b+ i! v; m
三 数据类型
! w/ n' h0 W" p. }( O- c! v struct sockaddr" h7 b, `$ b* a6 c
{
j2 O) @- C: c3 u; P unsigned short sa_family; //地址族, 一般为AF_INET
' a4 Y0 g) F0 _2 h7 v; B: D, Z char sa_data[14]; //14字节的协议地址! {" L" ]- B+ U3 K0 X: W9 e8 W
}
" O6 ^+ p- G0 b* c0 C0 Q. f% ^* e; H+ I4 c* j
struct sockaddr_in
' u" f1 [% {8 g. |, A {
3 F) v; q- F( {6 ]2 F$ b short int sin_family; //地址族
& o& y! X8 n8 B+ S4 C unsigned short int sin_port; //端口号8 ~0 ^( Y h0 C6 u$ J
struct in_addr in_addr; //ip地址2 ?! U* `7 C9 Q' n
unsigned char sin_zero[8]; //填充7 G6 l# o: `2 r
}
6 A7 L2 V, r! m. d3 f6 @
+ N: p5 I% O* z! S7 o四 常用函数* V; F3 _# R+ }
1 socket()
6 ^7 R1 v2 \% M0 h 头文件:
9 V" j1 X& k& k& j5 G: B #include <sys/types.h>
3 t0 H' z, S% `- I- x$ F #include <sys/socket.h>" u* Q% C6 C& m# ^
函数原型:
4 g( l+ H8 w; ]$ R( b int socket(int domain, int type, int protocol), k7 R6 v% x* i) L/ a0 z1 z
domain: 协议类型,一般为AF_INET/ f/ ^' D! @5 a( ?1 I
type: socket类型5 L$ u# _* U: r5 D# F
protocol:用来指定socket所使用的传输协议编号,通常设为0即可
2 X% ?- G8 l& |, n3 H! a5 K* |0 t Q
2 bind()
6 g4 c* L0 h8 X- D ^7 @/ I2 R 头文件:
# Q# f# X4 @8 a( r #include <sys/types.h>
( c/ {1 l* E4 n #include <sys/socket.h>9 N) P$ V" K# j" {
函数原型:
) l' z! u B8 s9 c# W% ^ a- u S int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
% I; z( A4 ?# D+ ~- ~! }) n1 ]# g$ c sockfd: socket描述符
" l' C3 g, E+ X0 O/ b my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针4 x3 C! c' F0 G2 e* h1 D' D' N
addrlen:常被设为sizeof(struct sockaddr)) A2 i* s( ~1 I M0 {7 B
! K0 S9 v! h& H F2 a0 g 3 connect()
; h/ L8 |/ k8 j5 b$ L/ ~8 I 头文件:
; _7 B7 I' g i2 g #include <sys/types.h> 2 h+ B7 [/ X( P
#include <sys/socket.h>1 o" L( b, y7 Q# P
函数原型:
7 B6 ]: S* R+ J# n int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
: V: Y' \4 F; v6 p) ?* d- x sockfd: 目的服务器的socket描述符9 s2 t' H* I( Q7 k1 D9 X
serv_addr:包含目的机器ip地址和端口号的指针/ p' p' O* X% I8 B
addrlen:sizeof(struct sockaddr)0 h1 H( ]1 o5 g4 X7 d0 Y
1 i, g% d- n N( h% l2 m( B/ x# P
4 listen()* K! l+ f% g0 H" M% H9 B: {4 `2 {
头文件:0 E# ]; ?2 R$ p- W4 w b, r% j
#include <sys/socket.h>
% f' }, I/ N+ z! e6 O; V 函数原型:
- N, F6 L% {9 @6 k0 L/ s int listen(int sockfd, int backlog);
7 E0 o \, @, |3 O& H6 M: y- t sockfd:socket()系统调用返回的socket描述符
6 _' h8 K/ P7 I; N8 B z backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。( A: O6 H7 D6 D' m
% Q# o/ W, x, E' }( n 5 accept()' Z! J W" `% `+ @ y! \% ]
头文件:
; I" B& |# M8 x O/ l u. T #include <sys/types.h>8 i- \) z$ @6 [
#inlcude <sys/socket.h>/ Q. e% f7 l( N% j+ F* z4 k
函数原型:% \9 U6 E# D+ F$ g0 Y# K. H& D0 N' U) F/ U
int accept(int sockfd, void *addr, int addrlen)2 ]* ]7 D, I% O7 [/ A" l+ I
sockfd:是被监听的socket描述符7 [5 O- F- l9 x0 Q# ?7 q
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
/ W4 \+ B7 v- K addrlen:sizeof(struct sockaddr_in)8 _! s2 S9 J# K' ]; L- ?
# m5 J y5 k7 j$ I' A- e
6 send()
( L4 C& ]2 V: y4 k* p( |. j' e 头文件:
/ U- \$ I$ Y [* ` #include <sys/socket.h>
* I* ^/ f1 i1 c [. H7 J 函数原型:
, H: H+ W9 G# r# e) I int send(int sockfd, const void *msg, int len, int flags);4 c9 ?9 J! H I8 U( b7 E& C
sockfd:用来传输数据的socket描述符
& T% R( T2 _/ M' v msg:要发送数据的指针
8 Z6 n0 u8 s6 f6 n' R4 }$ c flags: 03 b+ i, E8 z# k) E, ~% T# O
/ g! b1 M: z* y
7 recv()6 A, N# R8 ^' J' G; F& `0 {
头文件:
) E7 z" q" N+ I #include <sys/types.h>
+ q5 J: [8 t6 B5 ~+ @8 `. ]' @ #include <sys/socket.h>
, u/ h W" C$ E 函数原型:' M3 q1 U6 p! x. n v. m5 \
int recv(int sockfd, void *buf, int len, unsigned int flags)+ _' E' u6 }5 `( X
sockfd:接收数据的socket描述符
* y! ?# R0 j, {/ u; y( G buf:存放数据的缓冲区( x2 M% ~6 h3 d: h5 P
len:缓冲的长度
5 F1 B8 T! f9 ^( `: \ flags:07 _6 A, U6 j& c
d k* C8 ^# o( v 8 sendto()
5 D9 x4 }7 a0 m 头文件:
, P9 V* n6 \9 M0 B+ [% G' {$ m #include <sys/types.h>
3 z3 s% V8 f2 h #include <sys/socket.h>
# w3 G$ H$ G- M- J( T 函数原型:
3 I' O, O9 U5 J int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
! n) N6 {% `3 M- M* Y% A8 B- a; s
* Z) e4 ^6 N- T ) C2 H# s8 T2 a
9 recvfrom()
6 s( W. n6 `" O! C 头文件:
7 ^+ I5 |" M" @8 S5 g #include <sys/types.h>; ~/ z" @- N6 l8 f" x6 D8 W; d
#include <sys/socket.h>( x+ P6 U, h+ {, e8 s
函数原型:, K4 }* r X* D& ^ w6 ]* J2 i2 d- U0 j
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)3 z+ F# ?) @! o+ G
# t" [/ s) P% y5 O0 r+ M. x 9 a q ^' e. e% h
10 read() write()# X& Y# m$ ?3 R" \, e
int read(int fd, char *buf, int len)) R2 Y; m% j/ ^- l/ O+ Z7 U) N
int write(int fd, char *buf, int len): i4 X/ d+ L3 J
$ U# A0 p3 v% g+ i) G 11 shutdown()- y1 Q6 p7 Z, N% J7 c
close(sockfd)
7 n% s' s/ S& Z7 T0 O9 s& i" p1 f' g4 ] int shutdown(int sockfd, int how): x/ P, B* B5 f, {/ W
----------------------------------- [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等) ) j* O/ @$ ?8 L, w4 N- G
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
9 O+ j. y+ I; T5 `<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
; t' t9 J. _4 a! K/ \1 l) X' s2 j<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等6 k' @9 B4 f3 t- l3 {
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
% j/ G/ a! W2 \# B% G* T1 }<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
2 k1 X9 a' V. ~6 k<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件 m+ N4 d8 ~/ `& W2 R2 O2 H+ K
" r7 y$ M( ]9 K; s: C7 N: U/ \- |
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等+ u2 M1 K8 `# w' X: q
#include <sys/types.h>
9 @3 I6 [/ P% j: J }6 E! r
% y- @$ d }* e& G# v3 ]#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons; c8 `/ S5 H0 I% P3 N+ p+ a
#include <poll.h> //poll,pollfd
* S! Q# _/ E8 x i4 n#include <arpa/inet.h> //inet_addr,inet_aton7 c w d* E4 L/ P" r# K
#include <unistd.h> //read,write+ r" k: Y% v6 |
#include <netdb.h> //gethostbyname4 c. w6 l& C6 U# h! X
/ t9 S' l7 `; O/ j1 L( W; \#include <error.h> //perror
7 R1 N* A5 T9 i. u#include <stdio.h>
% b: Z' N) o6 ^3 {- p2 e#include <errno.h> //errno3 g# ~2 b) y+ S" ^0 P
4 A8 G' \/ I( \4 v9 H6 i
#include <string.h> // memset
1 m- I. i( \2 W1 p#include <string>
7 c3 ^& j# P2 P, I" T#include <iostream>
# X" h1 H0 h% k2 ]( C9 P( ^3 R' T9 T9 ?4 z( `7 }% M4 p3 G
|