|
[size=13.3333px]一 三种类型的套接字:! J, _8 y9 A- c# \8 }
1.流式套接字(SOCKET_STREAM)
" }3 E! C1 T6 i" {! r 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
! Z& s6 D. n* W. J+ Q% F2.数据报式套接字(SOCKET_DGRAM)- z$ k& I4 M/ D/ Z$ @0 C" {
提供无连接的数据传输服务,不保证可靠性。
* ~# [( S5 C/ d; H- k, y! C3.原始式套接字(SOCKET_RAW)" m) W. @( T6 s3 n( _5 L
该接口允许对较低层次协议,如IP,ICMP直接访问。8 L$ W% @8 U, W, {. x# e6 D5 N
# A% j0 ^/ z: K; Q, N: G3 j
二 基本套接字系统调有有如下一些:
8 u6 [5 m6 y Q 创建套接字: socket()
( ^$ U( l' D' w- } 绑定本机端口: bind()" g# Y! n' z5 d( C& L! K
建立连接: connect(),accept()
4 \, k2 O& G; B 侦听端口: listen()
- ]9 E. ^# b* u8 ] H& h7 Z" z7 u0 o 数据传输: send(), recv()2 O% c" n/ a5 c
输入/输出多路复用: select()
0 o8 c8 m: V+ M! M( m 关闭套接只: closesocket()
3 g: T- B- q8 A2 A* {
5 R& y4 Q7 i' n. I三 数据类型
$ Y' l$ D+ }$ A+ R7 \ struct sockaddr' ]! s4 V8 i3 D j
{5 q0 L* h5 T) [! |1 N
unsigned short sa_family; //地址族, 一般为AF_INET- i! m, L. m7 _) z6 ~: u& i
char sa_data[14]; //14字节的协议地址
; V( |- P5 z% R3 u& W. m0 G: H- f2 A9 l }
f+ P0 u7 K f( n. G4 F- J' h4 [2 o. u) q) n9 g- S/ N
struct sockaddr_in
- N/ v2 ^1 L- }$ c {
; J7 {4 p& O* E* l1 a/ j: k* G short int sin_family; //地址族! a. t$ j: `( I9 f( U/ d( s
unsigned short int sin_port; //端口号- d% i! F9 |) ~# a" r( w
struct in_addr in_addr; //ip地址
l K% g3 j! T# q1 t unsigned char sin_zero[8]; //填充
+ q: r9 y. G! s3 g: F }' V: _, S7 h. d! @) L5 o
& x( r/ u% V4 Y& }, d四 常用函数
/ m/ }, x2 C: r9 ^/ v$ V: c: u1 c 1 socket()
: N( Q- `& x1 n0 Q 头文件:
+ ?3 i, A6 n% M! c" D/ k0 q #include <sys/types.h>6 u6 }( S2 t, D* d. I+ p: f
#include <sys/socket.h>% S" U* E+ d2 x: t
函数原型:& i( ^4 C5 X6 I& r9 @7 _$ ^+ f
int socket(int domain, int type, int protocol)
) j6 _. u+ l. ^. X6 c" ~' D domain: 协议类型,一般为AF_INET& ]' s- p+ k$ Q/ q
type: socket类型, d4 g; T. R" c. G- }! {
protocol:用来指定socket所使用的传输协议编号,通常设为0即可) Z) y' Q d, k/ l! ^. O+ m- ^
4 `2 T8 M! E/ {$ p 2 bind()
Q. Y/ \1 G1 }3 J 头文件:
, X) N7 z2 U& x% a #include <sys/types.h>; M7 R2 d3 L" U i: H
#include <sys/socket.h>
H3 @8 i7 t9 L, F 函数原型:8 W2 v( b- l2 @: v/ F7 _; d5 c8 z
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
- v7 n: ?, f- ~, ~2 X sockfd: socket描述符
6 F8 x6 M7 ^* b( i7 d my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
8 F1 t3 ^+ ?3 ]' m addrlen:常被设为sizeof(struct sockaddr), W3 r! T, B* l4 O: w
* H& S+ ]* b( F" \4 K& W
3 connect()$ q* p+ I; E, W* B F) Q, F
头文件:# W! V; a: K+ P4 \2 H
#include <sys/types.h>
- R9 A- v, b. O0 H+ l; L3 ~7 } #include <sys/socket.h>
% q& b* h# u( Y, x- l; t: ]/ S 函数原型:$ v! ?7 y5 f7 C& |% g
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)! |/ W& g5 s2 l0 ^! D1 _( M
sockfd: 目的服务器的socket描述符2 E( M" c) t7 _
serv_addr:包含目的机器ip地址和端口号的指针
6 Z$ ^, X0 r6 G W" O addrlen:sizeof(struct sockaddr)( d6 ?" k0 E0 Y: M' n
1 R2 G% r) h% @ 4 listen()
/ O/ e3 A& L9 `0 U5 l2 E; b1 ] 头文件:9 G3 @3 D8 f: H1 Q" f; n5 s
#include <sys/socket.h>
3 V/ q- c* F/ R+ r 函数原型:
+ p: P" x8 C3 o0 P/ p6 t6 v. Q int listen(int sockfd, int backlog);
3 t0 {$ r) M- b9 _* H) a sockfd:socket()系统调用返回的socket描述符
! }" ^7 v2 ^; ^' P backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。- e4 z) k1 A' Y. K5 u) P. ~$ a
8 m6 t* b% n4 u
5 accept()8 {8 I( S9 p: H4 C/ K( X
头文件:
. `& j2 U* Q! X# K) _: S; U { #include <sys/types.h>
, K7 V! b5 C# E1 z. S3 Z #inlcude <sys/socket.h>
2 x: {: ^! w" D' b, _ 函数原型:
4 A- p/ B+ [4 V int accept(int sockfd, void *addr, int addrlen)
! X3 t: e [& u, S2 ^1 V sockfd:是被监听的socket描述符# C- @: T; P! o( n- [
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
3 Y1 [" \) e' V! f" P addrlen:sizeof(struct sockaddr_in)* A3 }: `+ r5 d" k: V8 a
' ]4 g2 _7 w2 |+ _+ i 6 send(). x5 E, `$ Y& K5 r$ g1 M, t; T
头文件:/ u: C, U4 F2 R) d
#include <sys/socket.h>
) r! E u7 m. a: @2 ^ 函数原型:! X8 |4 n# U4 M3 v1 p; y
int send(int sockfd, const void *msg, int len, int flags);
6 s' R0 j3 S4 n& j& l3 [; N sockfd:用来传输数据的socket描述符8 A' w8 r& g8 i& x4 l0 l7 j
msg:要发送数据的指针 ) t$ a" L# f) e' C7 B+ M* U
flags: 0
6 W5 _, E# K7 {; a
% X$ L+ X4 B( t0 u( L$ v$ d2 Q 7 recv()3 u/ s5 Y* J8 n4 B8 T
头文件:! I. p% F' @+ c. t& B2 }
#include <sys/types.h>
3 d5 n7 K* r$ C! ]4 F1 P6 v #include <sys/socket.h>9 i s! |* ~( c5 n
函数原型:
+ x7 d! v% r$ a int recv(int sockfd, void *buf, int len, unsigned int flags)
. U; G7 L( S J) p# A5 i sockfd:接收数据的socket描述符/ }# A1 a& d& i# q
buf:存放数据的缓冲区
$ {: K( @% H, @/ Q len:缓冲的长度
6 l6 ~( {9 P9 o' K2 T; f g0 K! Z flags:0
1 f0 u! C" c6 T4 @/ ~: o2 `9 x
8 sendto()' {) ]& t4 T+ z; q* I
头文件:' ~$ G8 z% C+ T5 P0 _5 _ c
#include <sys/types.h>: u0 V& \% a+ d3 y7 l0 Q
#include <sys/socket.h>$ Q9 j$ q$ l: I5 a& y
函数原型:
: v9 }# ?: z7 u$ A2 q+ m w int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
* o; x; E ?0 \& j$ N! g: a
' W# v* Z R( H+ l0 N . `5 R) [' N9 K2 j5 T
9 recvfrom()8 ~2 V( O# f) `6 f; q5 z
头文件:
6 d3 `+ b7 c: i# s- w* @/ { v9 M1 R #include <sys/types.h>
! g) w- k# l* B, {- B5 i+ ] #include <sys/socket.h>) u: m3 M6 h5 T6 _8 X2 V' T8 K! c
函数原型:: l) d- ^( o" ?
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)
6 [7 t- n5 z1 @, w- e9 v0 N# n1 |/ v$ E; ^3 ` W
$ s- {9 O- d# L+ h
10 read() write()+ _7 o+ F) Y; K# t' F9 x- C
int read(int fd, char *buf, int len)- E) t" y& [7 F' `3 ^
int write(int fd, char *buf, int len)0 M% R4 Y- u& R. A) e, X. B2 A* N
9 c! d2 L) Z* s _
11 shutdown()
# a! n# N: |2 n+ Z close(sockfd)2 w9 [# k" X; q* P9 b& A2 \- o
int shutdown(int sockfd, int how)
: s3 y, C6 ~9 ?* i% a( 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等) 4 \8 A# ]( i9 _9 L: p
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等1 z8 `4 |& @( Y( ?! f
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()5 b, i. [6 N5 B0 f! g
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
4 g* `0 ?$ k6 L, q1 m, }9 ?4 h/ @<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
7 [$ E3 U1 C6 @2 ]2 Q6 h<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
, @* P9 K4 [( j7 N# o0 E- Z5 W<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件2 C+ O5 u. y" T6 F U; `
) A M3 j# k/ a* X
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等! ?6 n* L8 s; H+ w4 p \" |
#include <sys/types.h>
1 t! p1 z& G+ Q
& ]/ z( a+ ^9 J s#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons$ g+ B: ]- C9 ~3 g4 P/ g& E0 Q
#include <poll.h> //poll,pollfd' _4 V, ] p/ s7 }9 y
#include <arpa/inet.h> //inet_addr,inet_aton
1 n" z8 F1 a$ R! j( V/ d- u#include <unistd.h> //read,write
1 y- t7 Z, O) [( k, c3 W* ^#include <netdb.h> //gethostbyname4 l5 ?; g2 A5 y/ i' S- q
. }' B# _7 S8 i8 ]4 @
#include <error.h> //perror
% g% n2 M. _! z! J& N2 ]# t9 b#include <stdio.h>
$ k8 d) ]* g7 b; q: V#include <errno.h> //errno
7 E' ^" `* W7 C7 D6 e' U! ~( n
& t, f5 E6 v0 A. N% \& _% i1 z#include <string.h> // memset( r0 H4 S! K" ^5 |6 {) ~+ r
#include <string>8 ^2 e1 i# Y2 J0 _
#include <iostream>$ H& y& R4 v8 d* j
% R, R% u- N) G8 j9 C |