|
[size=13.3333px]一 三种类型的套接字:3 a+ s4 N8 \! ]3 M" Y' ]
1.流式套接字(SOCKET_STREAM)# T1 p3 f2 ^' @ [+ Q9 Y* Q' f
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。9 U; \$ s( p& `4 U9 P/ `, h* v1 _/ R* D
2.数据报式套接字(SOCKET_DGRAM)
# D) P/ Z: R E X/ K/ D 提供无连接的数据传输服务,不保证可靠性。
- T" w& I- _ D3.原始式套接字(SOCKET_RAW)
s" u; y+ d0 B 该接口允许对较低层次协议,如IP,ICMP直接访问。
7 o( V/ Z0 f0 u& Q( |+ K9 A* r+ n/ z$ \# s% B
二 基本套接字系统调有有如下一些:5 W6 r8 r4 G3 k
创建套接字: socket()
9 c* {0 l8 k% J( M' E; j; i 绑定本机端口: bind()
' \- e0 v$ _+ `- Q& m 建立连接: connect(),accept()( {0 ~/ D% N1 X3 ?/ a
侦听端口: listen()1 [; C \" W& j% K
数据传输: send(), recv()
) d% X- P {+ i- M 输入/输出多路复用: select()
; T5 O' f, B; u. X. I: A4 [* T6 L r 关闭套接只: closesocket()
1 R# B" i4 |5 g$ t* T+ x3 s D5 r, M* L4 |/ s, V' A
三 数据类型8 y7 {3 c% B ^" J' W
struct sockaddr& L! E( z$ H3 J. o, Q
{. b8 G+ J1 o& ^ _) G0 u/ F
unsigned short sa_family; //地址族, 一般为AF_INET
1 ~ A$ f# N* ?) G char sa_data[14]; //14字节的协议地址3 D. f, V5 E$ a; @4 Q: W6 J; m, ?
}
5 _% v! @: s" T0 o
$ f# d+ V N4 A' f# d struct sockaddr_in
# a, Q# g# A7 _$ k ]3 \; i {
7 l, ~/ N5 x: |8 g# p% N+ k short int sin_family; //地址族
/ |, s2 I7 C0 \" f4 B% n8 s2 y% d unsigned short int sin_port; //端口号
! i, I5 \7 w( N. g, ^$ M7 ^% W: N- k struct in_addr in_addr; //ip地址
l! @) G6 K& b. {, O: g unsigned char sin_zero[8]; //填充% r. o8 o1 J: G% S6 [( ~6 n
}
# \" P' p8 o% O
1 `% j/ C5 y, N+ @7 ^四 常用函数
" Z& m6 C! _3 {, i5 ^ 1 socket()7 J0 Q) g; z6 `. g) w
头文件: 5 d7 y7 R; H Q& |# X! @
#include <sys/types.h>
4 E X5 K8 i% e2 U' G+ U #include <sys/socket.h>
2 O- V6 s; G2 ` 函数原型:
0 s+ Y7 A2 K- I6 w+ V# F- } int socket(int domain, int type, int protocol)
9 B6 c- ~: U$ j domain: 协议类型,一般为AF_INET& q3 N7 J! H K5 L1 w2 i3 i
type: socket类型
5 r1 J) b& j& i% s' S0 V3 o( D6 w protocol:用来指定socket所使用的传输协议编号,通常设为0即可0 I- h- ~' @5 x7 u7 C
" K& M$ q9 n: } 2 bind()
- b" ^0 z1 Z! n' e, Q 头文件:2 }" B3 ^3 l( R _7 N8 k0 e* ?
#include <sys/types.h>
6 t. z" e) h/ o% `) B; h #include <sys/socket.h>
, }1 W R; @. Z( x9 \7 c3 Z 函数原型:; k7 J" H7 B6 f z" \3 [) \
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)) H- t g9 d3 \" y7 g
sockfd: socket描述符1 F ]% F1 r: o# N" J
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针4 N" ^( c! r+ B# j' W
addrlen:常被设为sizeof(struct sockaddr)
+ k% j1 F! [, o& k2 Q$ H( T
) u9 I3 X. h; F 3 connect()
9 d; @1 }1 u9 R* h3 R 头文件:6 _: b) J5 V, C3 T, j+ [
#include <sys/types.h> & R; y% M! s. V# Z5 @% q
#include <sys/socket.h>/ p% q, v$ z+ B8 S5 d; j8 ~
函数原型:% L5 N7 ^5 y2 P9 M
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)" t6 u7 d2 R& n9 J3 d
sockfd: 目的服务器的socket描述符5 b. n* L! Q7 } |, b
serv_addr:包含目的机器ip地址和端口号的指针' |. L; N, ?! ]% A1 }4 t& ]6 q
addrlen:sizeof(struct sockaddr)1 F$ b$ I9 z; ^3 s3 L- ]" U; q
0 E; n9 B! f i; B( K' M
4 listen()
* J2 K6 F" u0 x: [; y- K 头文件:
4 N, `$ b3 F# E, f #include <sys/socket.h>4 F3 T5 R& c! f9 U) [5 o% @* _
函数原型:5 ?4 V I7 @" U
int listen(int sockfd, int backlog);
0 c; U6 n. M" ^0 b \* t sockfd:socket()系统调用返回的socket描述符& g3 d1 {! F% Y' f. |
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。
}) Q2 m, u/ f1 C* I6 i" e4 {
2 P5 I3 Q3 H% T 5 accept()* |. a% d9 ^" v6 m, G
头文件:
8 j8 ^/ ^7 l. L2 z9 [ #include <sys/types.h>
: C, x/ j y% Z" a #inlcude <sys/socket.h>
. j& s, E6 W+ M' Q2 ?' W 函数原型:2 f/ ?9 X+ Z0 q/ o" m, |# X, S C
int accept(int sockfd, void *addr, int addrlen)
" U% g: |- A; g/ A( y( y) T sockfd:是被监听的socket描述符
; x' M" a7 M/ t addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息3 T0 U* U& D' Y
addrlen:sizeof(struct sockaddr_in)5 L! c3 x7 M: A5 b' F
- I7 z. s: D! u ~, d7 Y- g% S1 n! B 6 send()" G! x* ^0 x' b- j3 Q
头文件:, t2 ^1 Q& A5 g+ u' _
#include <sys/socket.h>
% f9 E% H7 U2 `! Y 函数原型:5 ]8 B8 V) ~2 t. a1 y. R. n
int send(int sockfd, const void *msg, int len, int flags);/ a2 h0 U" m( B# ?
sockfd:用来传输数据的socket描述符
2 e, I. k. c/ a3 @. S6 @$ I msg:要发送数据的指针 ! a- I, [8 a+ R) E: l8 N1 V1 Q
flags: 0
r7 p7 y7 h9 V7 Z: G$ U
, b0 @% C. f1 w 7 recv()
9 d4 f& Z" B$ l d 头文件:
* z. F) l6 D1 l5 I# _: a# P #include <sys/types.h>
8 W3 u3 G7 u2 b6 S' k. l- c #include <sys/socket.h>
& c- S1 w/ v2 _7 T& q 函数原型:3 O/ B' U9 i: S( t7 N6 x
int recv(int sockfd, void *buf, int len, unsigned int flags); S. n; R# h! W( H
sockfd:接收数据的socket描述符% H' l. ?" Y+ R& F' U4 x4 s" F
buf:存放数据的缓冲区
& H' Y) {) @$ ?; ] @/ ~ len:缓冲的长度
2 Q2 Z5 \2 P( J flags:0
& c7 r, |& e; g% q& {* z; ~
8 m$ z7 l$ q. @* C5 f 8 sendto()9 L7 b8 q$ r# }8 S* b4 N3 V- A2 S7 y
头文件:* D' s' G0 K# O6 P4 B) L0 `
#include <sys/types.h>
, r$ Q* X' D9 k. S+ o ~ #include <sys/socket.h>! t3 ^! a0 W B0 a
函数原型:1 p2 z7 U8 U0 |* R, S
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);, U) N& B; c& s7 G' J0 ^2 W8 v
, z' g3 J8 G( I# ]/ F+ } 0 _+ f$ \7 ?) {. i
9 recvfrom()6 \" c5 g6 }& y2 n5 `- k2 ]# y& o
头文件:
. s' N0 m, S7 ~+ t! M' J #include <sys/types.h>5 L1 @9 p1 K+ x. {; F
#include <sys/socket.h>, r/ ?$ I3 x, a9 e8 ]# S8 H
函数原型:
' [- B& F, S- ?' Z: N, B# c int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)
2 k8 X0 n$ D& g% ~
1 |% C$ i+ ?4 n8 s
- _$ w; A- Q0 v6 S 10 read() write()/ o8 y) e q- b4 z* m
int read(int fd, char *buf, int len)- T' U3 Z" W& Q/ i
int write(int fd, char *buf, int len)
8 ^& U) M0 G- \& ~. _
2 _) M5 q* l% s" r1 a3 [% L 11 shutdown()+ t7 s6 a! C7 s
close(sockfd)
" N( O& L9 w8 x9 A. u int shutdown(int sockfd, int how)
6 H6 \( @) `" B- K* U' e4 x0 c$ r----------------------------------- [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等)
5 D7 M% H V4 N. s6 M) Y1 _4 J* s<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等+ \3 c* d! v! ?, ~5 s$ x
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
9 o& K/ ~( c3 Q$ k4 U+ L1 h2 e<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等/ u- f4 `: ?8 h5 _8 n
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
! Q# N/ f" z' [. |<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
7 g R( V: u1 J% f$ e* K; ]! a0 ~<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件( p+ H4 B6 u/ o' h2 e
* `3 D3 l C! B* I[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
5 |/ a8 v6 S7 N* z% Y( |# _#include <sys/types.h> 6 B e& n' A: I. A' Q0 H0 I! I! g% ]
+ L& p4 b8 j0 @" t) d0 f#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons! \ G+ @3 ^4 H: D4 {2 q
#include <poll.h> //poll,pollfd
]! A; k Q" A6 S, }4 X#include <arpa/inet.h> //inet_addr,inet_aton
0 p, o9 G% \+ y+ ]) _7 h#include <unistd.h> //read,write5 k1 @$ [1 Z* T- Y1 b4 g
#include <netdb.h> //gethostbyname
/ }/ r3 X4 t$ ^7 e: ^$ U* l `% j3 O2 ?3 C- _: K9 O
#include <error.h> //perror! l# a ~# l( H @( u
#include <stdio.h> X' Y8 l% b2 w" N- c8 O
#include <errno.h> //errno
5 {7 P0 s6 ` q d$ v3 ^: b! b, L' i( G/ _; m
#include <string.h> // memset6 X3 Q% b7 r+ r& ~" J
#include <string>% J J4 r4 L5 X* R- R
#include <iostream>
# w. Y2 i3 M. Q. j
, W8 y& e2 W9 F5 v5 a |