|
[size=13.3333px]一 三种类型的套接字:
! ]5 ]# e; H c& d: G+ e. U( Q1.流式套接字(SOCKET_STREAM)
& W K* j; v* i+ \( k* |) D; I 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
2 _+ N- E2 R, N- F2 x8 Z% F2.数据报式套接字(SOCKET_DGRAM)
: b3 ], k1 t. [1 J: X& l: Z 提供无连接的数据传输服务,不保证可靠性。
- e. C- p2 ?0 s5 \3 X. r& i3.原始式套接字(SOCKET_RAW)0 i4 T5 g5 ?/ \
该接口允许对较低层次协议,如IP,ICMP直接访问。. R- _. S; w$ G' D% C
1 s8 N: I3 I8 X$ w9 Z% ~' Y
二 基本套接字系统调有有如下一些:' S! T$ S5 R. J/ O% b
创建套接字: socket()) ]# @- }& X7 q' ]# g
绑定本机端口: bind()
- }: `2 N! I9 V% N0 ~9 y: w# c 建立连接: connect(),accept() |% [+ f7 z+ H
侦听端口: listen()9 J" n5 ]2 G: d6 c
数据传输: send(), recv()
- ? U1 m; J3 d$ Q) Q5 t, _; Q 输入/输出多路复用: select()
' [" e+ N* _" x. z$ f' p 关闭套接只: closesocket()1 B! d5 B b' F7 q+ G& H/ |
8 M h9 Z8 m6 ~1 C
三 数据类型( m. M. f4 L1 O1 m7 p2 p
struct sockaddr
: F3 H7 @, Q5 q2 s* Q4 c {! y9 k( M: b% }$ P( y4 X6 j
unsigned short sa_family; //地址族, 一般为AF_INET
: \* n4 M- _; y1 S5 k. J. n0 G4 F# d char sa_data[14]; //14字节的协议地址6 v# m o. F0 _% G# k5 I" A
}
8 \0 L, H/ k- V7 J1 j/ t) f/ r5 q) L: ]9 d, F+ U" F
struct sockaddr_in; d# Z( }# s% i( k0 w6 Z
{$ V# b4 C' _8 X |! M8 }' @
short int sin_family; //地址族
% z( |. j4 ?4 @4 F; ~% V3 c/ B unsigned short int sin_port; //端口号
0 z9 @3 s/ f, a: s) m. c- ~ struct in_addr in_addr; //ip地址+ I$ ?; h/ y$ W' ~5 n
unsigned char sin_zero[8]; //填充" M. _; z" i" m! l9 ^) X; P
}
* ?8 c/ O8 g& |- D7 @9 T7 F+ D7 k
/ a4 U& A' |/ y& u/ D四 常用函数
/ o0 K8 g8 q- T# L 1 socket()7 b+ _' m2 C# O' R7 Q3 {* J! X
头文件:
( ^, u% j# b3 m; g; M H) @ #include <sys/types.h>' N7 U R! b' k3 k
#include <sys/socket.h>; ~, k$ A' |* F4 Q' }/ u( W) G
函数原型:& m9 j; c) S4 R) b' v: p
int socket(int domain, int type, int protocol)
7 D& J; s9 D2 u9 m7 h( t0 V; e domain: 协议类型,一般为AF_INET
4 `6 G* [& q; @, g2 a3 u type: socket类型
/ l: X7 Y S" M1 ~& W protocol:用来指定socket所使用的传输协议编号,通常设为0即可
- B2 q/ x; v. B: m4 t- T' o
5 ]0 z3 j# B! b5 R [6 c* a0 J 2 bind()! l% ?& C: @8 o d
头文件:; d, |7 E# h/ U
#include <sys/types.h>
v/ a) u7 C8 ~ #include <sys/socket.h>
- c4 P1 m- E! t) U 函数原型:
: g0 B" }$ j5 t. { int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
7 V, K: J- H, B* G sockfd: socket描述符
9 i! F5 { u- Y5 \ J L8 V& z/ ~ my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针- c% d& a: T5 c3 O
addrlen:常被设为sizeof(struct sockaddr): C- w& p# x( ]9 l; M
( [2 H# C$ j& y, d) c: k 3 connect()
7 ?8 r/ f* x% N# U, B& B* I 头文件:
) S" l4 x& R/ n9 _, g #include <sys/types.h>
2 v- b6 `, r: X' Q: w #include <sys/socket.h>. X; U# ]8 r0 G2 v7 l- z: Y
函数原型:
3 f; \& v! l V: q+ t int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
4 W1 j9 l- G& L, s sockfd: 目的服务器的socket描述符3 P& o. N/ v0 y4 i: T
serv_addr:包含目的机器ip地址和端口号的指针
, S" u7 q; o) {+ K; @ addrlen:sizeof(struct sockaddr)- x: L- L/ w& I' B9 o: L
8 v- }3 `' E4 `& E7 F% y- ]$ P 4 listen()
& a( c; z4 ]( S6 Y 头文件:5 _4 [5 V% s3 L
#include <sys/socket.h>
1 Y# B- V2 b3 @) A 函数原型:. ]' Q- f+ q! ^1 K6 j) y" e
int listen(int sockfd, int backlog);
, h% E2 n8 [# N" { sockfd:socket()系统调用返回的socket描述符
1 b M! l: j9 `! k+ r) i backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。' Y# ^) Q, y j y R. t
; x& r5 ^0 E) D1 x- @% L
5 accept()
' k5 ?8 z: [* r- o# e* M' B! s& { 头文件: 8 B# S) y) H$ b |
#include <sys/types.h>
! D$ V8 j. m) W #inlcude <sys/socket.h>
; v8 K" f; {2 M/ C( Z! e 函数原型:, c9 b" ~9 f6 c$ e$ t( ]3 x
int accept(int sockfd, void *addr, int addrlen)
i2 U f5 L/ r& @9 P sockfd:是被监听的socket描述符 E. M* b! M: n, }8 ~! H
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
; v3 F" g" J# G y, { addrlen:sizeof(struct sockaddr_in)* s8 V0 b- F6 P) Z! {: |: w1 _0 G
2 g1 X/ G- x: {3 p! L
6 send()* \3 x" E# ~3 E0 f
头文件:9 n# b; K$ e L, l
#include <sys/socket.h>
3 B$ ?7 H5 O- j: L, B: W 函数原型:& u! B" x6 s; i
int send(int sockfd, const void *msg, int len, int flags);) }, ^. K- B" m4 h) S g9 _
sockfd:用来传输数据的socket描述符1 b, }1 s& T6 D0 Q$ k/ i& b+ ]
msg:要发送数据的指针
+ O: J- v) E9 ~! t0 u$ s flags: 0
/ Y7 A1 K6 K' j! ~9 k* F ( e0 W; K) S. n# G, |$ [
7 recv()
: e- y& _& d, @4 N- |2 o 头文件: m. k1 N; W" R K- C' R
#include <sys/types.h>. b" J$ g7 q! O6 i. d& e! C
#include <sys/socket.h>
$ @. c- {4 a+ A 函数原型:
6 Y5 y4 y6 u" }: X B int recv(int sockfd, void *buf, int len, unsigned int flags)+ X8 ~+ z% j: M9 u8 A
sockfd:接收数据的socket描述符
2 j+ f& G" K! b buf:存放数据的缓冲区" t# X& ? }% R- H: j+ e
len:缓冲的长度
n1 R; @+ s" }" K7 @ flags:0
! U+ K( L9 y3 w& S
( K$ D" S) i4 S& p& j% Y6 m" o) I 8 sendto(); w- O5 _ \$ s, H
头文件:
) u7 ~. M+ u9 L+ D! g #include <sys/types.h>! o& y6 v E! L9 @) d4 l
#include <sys/socket.h>& j& ]! _: f6 {. |. V* b
函数原型:5 |+ N/ i. [4 w4 O" M9 L* e2 n; v4 y
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);' x/ M T) d- ^4 z6 m8 i1 C
' _/ [% K. ?3 S
0 c& k0 S( X8 g' R) ]" i0 c7 r 9 recvfrom()
( d6 U3 H- X n8 G9 F 头文件:9 I6 B' o- w: S
#include <sys/types.h>
& y$ y ]! [7 z8 C3 l #include <sys/socket.h>7 b& Q, w; Y v* ~$ n+ z- {+ }
函数原型:
! y4 X) y# J- _4 P G7 b int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)
9 c4 z- S6 s) G+ ], s3 i. f& W# P4 @
, _. N. Y5 u/ f. i/ g J$ W 10 read() write()0 i. g- D' c* N0 _. i
int read(int fd, char *buf, int len). y/ g3 }% A$ I2 h
int write(int fd, char *buf, int len)
" M {" K; n9 ?$ Q: w) B+ F
6 Q9 R) _1 O8 v V" h7 k 11 shutdown()1 i- Z4 I2 C4 t$ M+ x* p
close(sockfd)
: T! t" p3 N4 b" ]3 ?$ E int shutdown(int sockfd, int how)+ v8 O2 m# v: j* F
----------------------------------- [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等)
) I" u1 m$ X7 y/ \% V; _<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等" _! V% _( @- }0 H$ ]" B N9 s, p
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()" g! m5 n) U6 ^5 p
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
! {5 B4 L+ F) _8 l7 T<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等( m5 C4 \2 O7 k, A1 t
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
* X' d {6 t& ?2 z<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件
% W. p8 r! q; h1 `+ _: @8 m6 P* h; \( |2 n# S
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
" n" i" r& s* W/ X& w#include <sys/types.h> ; g* {- C& C, U: L' L y
6 E) x+ O& N2 J7 k
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
' W. L$ ]2 {( O7 J3 w$ A, ~#include <poll.h> //poll,pollfd
: q/ r G+ \& |) q' P) i#include <arpa/inet.h> //inet_addr,inet_aton! P- C" B( r, G; }
#include <unistd.h> //read,write
# N! L0 i5 m- w' O#include <netdb.h> //gethostbyname$ M$ Y8 T! ~1 r
1 u* ~( d) U1 e% d/ k7 n; L5 h- N#include <error.h> //perror3 q* d' L+ F: F8 J4 l+ F/ p
#include <stdio.h>, l5 G* x: g4 D) ?: a* V$ _, i8 J
#include <errno.h> //errno
' Y1 E* U/ b! n1 L! `% d a: A9 j$ O+ H) ~6 v8 s# n- a# Z; F
#include <string.h> // memset& w5 P* L7 v) D; v8 W, m! u6 U$ T3 ]: H
#include <string>
- [ ^( h& {8 ?3 p& V" W4 m* A#include <iostream>/ b# k1 `, ~* Y" S- |! \' K. U, m' F
7 p0 S& Q, O+ @8 X |