|
[size=13.3333px]一 三种类型的套接字:4 I( c' e6 O+ G. M; c4 Q
1.流式套接字(SOCKET_STREAM), u0 {/ L) j& d* q, b
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
8 j# n0 K& C+ s+ ~5 ~2.数据报式套接字(SOCKET_DGRAM): L1 a9 s! u2 \' e
提供无连接的数据传输服务,不保证可靠性。. _0 e( P! \" v" J% A) B# m
3.原始式套接字(SOCKET_RAW)6 `; b# m( x/ T- Y- d" j
该接口允许对较低层次协议,如IP,ICMP直接访问。
% u: v6 l" n; g3 r: }: o6 A- m' P/ B
二 基本套接字系统调有有如下一些:
7 Q9 f( r4 M6 J8 v 创建套接字: socket() M' u6 r, ]! L% t/ v
绑定本机端口: bind()
) Y' _7 V' q7 L! b$ @' W2 ?4 Z, r 建立连接: connect(),accept(): F4 \3 r% B4 t( _% Q& e) \' Y2 [
侦听端口: listen()6 w: c9 }, ?2 |
数据传输: send(), recv()2 w: ?8 Y! U9 M8 G }& ]. [& B! S
输入/输出多路复用: select()
9 E; O" _, H% H3 h4 h; j 关闭套接只: closesocket()
$ r8 C/ D8 B7 k: b # q C- E: ` y
三 数据类型* O9 d; [( E7 F* v0 p
struct sockaddr
# c7 V8 j; A7 f4 f( c6 M) k$ J. Q {
# M1 c# ]& O1 m' L W unsigned short sa_family; //地址族, 一般为AF_INET* [ t5 V8 x2 M9 Z* X" f- c% j8 A
char sa_data[14]; //14字节的协议地址
, _" N+ \5 M; O3 U% Z+ m }
& v& I# C) R8 v, U6 ~$ a \+ P! W/ Q( `6 @$ ^% d! g5 Q! o4 t
struct sockaddr_in1 ]$ m% |5 N7 s" N+ J
{
% m g2 c+ V, L+ R short int sin_family; //地址族
! x1 m9 I! E: _8 G" n7 }- r: ~ s unsigned short int sin_port; //端口号5 Q1 X% q; ?; g0 a; Q9 f9 S X8 C
struct in_addr in_addr; //ip地址5 X9 @; r( _7 s& C( z8 H
unsigned char sin_zero[8]; //填充; D2 E5 K' \; |) E& e
}$ ~% ^" z; F* X( |9 c/ T
! z7 x2 P1 z \! p8 M- k. y
四 常用函数
3 t2 k. q1 }, n 1 socket()
: o3 J+ m) `$ @ 头文件:
% {! `$ l. R; w; _ #include <sys/types.h>' a+ ?+ D+ g8 r6 g) |
#include <sys/socket.h>
" n7 G7 O# d( m4 b9 P+ P3 p 函数原型:$ [6 @( v% H8 Z
int socket(int domain, int type, int protocol); C3 r# n$ Y7 @7 ?5 b
domain: 协议类型,一般为AF_INET
/ g/ M( ?4 ~0 U/ V. q/ G& [ type: socket类型' C; J7 P) @8 h: O/ P1 B$ ~5 u: g* l
protocol:用来指定socket所使用的传输协议编号,通常设为0即可9 e! X7 U2 G4 W
6 o3 H9 x7 l' @; ]! J
2 bind()
7 ], ^+ |# t1 V, o" P$ f 头文件:' _* j/ q5 J# k* b O# x6 x) w
#include <sys/types.h>
2 t, h" d; |0 \* Q0 C( W9 B7 T #include <sys/socket.h>
0 h4 A4 f1 J2 g7 R& p* h+ e( ^" l 函数原型:
7 F: ]# f. w; a m2 c. B3 E3 C9 K4 m int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
( d1 M. P. Y& O2 |8 J7 G y sockfd: socket描述符% D2 _. o: m* m( N, T
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针: @4 B9 X6 p5 ?# M1 ?
addrlen:常被设为sizeof(struct sockaddr)
Q0 d8 X+ C* O- X1 V4 u8 B/ z0 J' F7 k" K% P7 K
3 connect()* r6 }+ r# g7 l
头文件:
; x* x; N" s0 b, M/ K c3 [1 k' x! W- L #include <sys/types.h>
0 w2 s- I7 m0 y, L, { #include <sys/socket.h>* P; C+ V* T: J( d, T+ d9 Q2 E0 k
函数原型:7 h) f7 z8 S' p' U) p4 \
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)9 J' ?( J$ Y- s
sockfd: 目的服务器的socket描述符$ F% Q, l; u" v6 t; N
serv_addr:包含目的机器ip地址和端口号的指针5 a1 L7 P1 ]" v* a; ]% I- D& u! e) g
addrlen:sizeof(struct sockaddr)1 M3 T* M" m+ i! b
0 d' \+ X) O. e/ Q( a2 c, s! b9 @ 4 listen(), ]9 V/ ?6 y, A) C4 {7 @
头文件:* m& E, i0 X k
#include <sys/socket.h>
+ ^9 I y2 I. \, t9 `6 t; C 函数原型:
( S5 p- X, U% A9 M c& P, E int listen(int sockfd, int backlog);
; L. c$ }- {8 p sockfd:socket()系统调用返回的socket描述符% [2 u2 j3 v( Q/ T
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。6 A4 [& N0 A2 ~0 ?. ?
" t0 F! I& i/ e* F 5 accept()
: x! @; j* V! k- Y' L' g 头文件: ; @, H/ A4 ^* `# t" n4 \
#include <sys/types.h>
: P8 N8 h' j+ |1 z #inlcude <sys/socket.h>8 S& ?! z7 p8 z8 b$ h
函数原型:5 _, o d5 a) v$ y. e( x! s" d
int accept(int sockfd, void *addr, int addrlen)
; W( L; B% h4 o0 w1 N sockfd:是被监听的socket描述符
, X: K+ x0 N" `2 h3 V( }7 U addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
# X' }+ N5 \$ h( w" R4 g' {, n* C addrlen:sizeof(struct sockaddr_in)
. x9 ?& C2 j0 T: I * q* M4 P; E# ?. p2 r X
6 send()8 q- g3 H6 M- m
头文件:
! h6 z4 ~& f* j; Y #include <sys/socket.h>& W7 u" I- ~9 D1 _6 \2 u
函数原型:
+ v" e5 f4 m- \5 a int send(int sockfd, const void *msg, int len, int flags);
4 i% T) u2 ~ n sockfd:用来传输数据的socket描述符
) L0 C% R' G$ b7 n* T1 E7 a msg:要发送数据的指针 ' D- w# o4 R& t, j0 q) M* x! N
flags: 08 T( y! P& C: L" N7 ^6 u' ]) p9 l5 M
7 ~" y$ t- g& ?* [/ X: b
7 recv()
3 I1 X; Y: g. r 头文件:
; u- S; _2 I b+ {" j #include <sys/types.h>
6 ]' G7 m+ R. z$ r$ f+ v5 M #include <sys/socket.h>* N" s2 L" b9 x" K
函数原型:( ?# X; v( h4 v6 Y
int recv(int sockfd, void *buf, int len, unsigned int flags)+ z2 |7 @; W& h) h5 j
sockfd:接收数据的socket描述符
7 {6 f- p q, V1 Y; ]5 h buf:存放数据的缓冲区
4 p! S, S8 x' }3 M- E1 [ len:缓冲的长度
3 P9 ?/ r5 n# Q8 @: |/ o# f6 e flags:0
6 S1 L) Z0 T/ E: z0 ~. P4 e/ }6 R4 w5 J
8 sendto()- F$ h+ p7 t) Z6 e5 B7 X1 V
头文件:0 d$ r8 B9 y. n2 ]* x- K8 t. v
#include <sys/types.h>
$ j3 m3 A+ x4 s1 {0 P #include <sys/socket.h>& c# Y6 E0 {$ D2 j+ E0 F
函数原型:+ {' X+ a3 E/ s8 J
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
- y1 w9 A! U" Z E: N2 M+ C5 |7 ?1 q . `0 [# Q t8 ]; S. L! }; F9 d1 m9 J
7 O4 J1 E+ U, q9 E. [ 9 recvfrom()
4 R9 H/ O" [1 g* J 头文件:; R& d2 ]+ \( ^# w9 l; ~
#include <sys/types.h>4 S/ a5 U% j& k. h6 W
#include <sys/socket.h>* O% u) ~ U( t% U9 |
函数原型:' [" r$ u$ b* s6 Q' t j
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)3 z1 S, Q- T" \
5 b/ r! h0 h9 d. e) e
& t8 [- v4 K$ ~+ T 10 read() write() N1 I8 D2 b! z, U
int read(int fd, char *buf, int len)) Z# w; u) E! d
int write(int fd, char *buf, int len)
# Y7 h9 g; e& l, P; O
|" ~* S0 Y6 H( F* Q 11 shutdown()
3 z9 U/ j3 L! ?: G* E+ ~8 W3 B close(sockfd)
( p5 {1 Y/ N8 Y. Z int shutdown(int sockfd, int how)/ A* G- p c8 j" H+ ~5 |
----------------------------------- [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等)
" c. a+ Z% P2 c5 n7 w* Q) q<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等- d4 @ r/ |$ j) c( N- p1 x; J
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl(): F* A: i# R: o- _( i, f
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
6 s* S" c$ L6 C) m% z1 ?( |/ d2 h<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
4 p) k8 }3 A" `<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等# x5 `" z" r; J" Y$ G$ ~( G
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件
7 t6 A$ l% [) X0 [% r8 D) |, @& J: [# A, U1 ?5 @5 y3 R; s
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等4 G' I5 N, d0 \* {+ h
#include <sys/types.h>
( J( \ d8 @% Z: T* t
' L" U% F+ h" b y#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons: V. O9 \+ F% g( l) z. _- @
#include <poll.h> //poll,pollfd
- s0 z) g& _8 l9 n5 s/ v* k#include <arpa/inet.h> //inet_addr,inet_aton
' k9 _4 a2 D @9 B4 ?( {) k#include <unistd.h> //read,write' X" I% t$ V5 L2 [+ v* G) S
#include <netdb.h> //gethostbyname h( a, \2 U' f
+ k% o9 ^( f4 J#include <error.h> //perror
. t/ L% Q( y6 r; ?: H, E0 [" Q#include <stdio.h>
4 [4 F* v) [8 ?% r) ^#include <errno.h> //errno! l6 R. `; t' l+ T7 J3 S
3 z, v& l% Y) ~; W#include <string.h> // memset
; Q* S- A7 A, s+ t7 x6 z6 E# A3 r#include <string>
8 e8 U% N$ P8 \7 ~: [+ v( X5 l#include <iostream>8 @ ~8 N+ C% N- e9 G" W& N
1 d) B4 `. P' P, O3 l8 Q. a" e% V+ U
|