[size=13.3333px]一 三种类型的套接字:
5 [# k: b4 b" V+ u- M( r' e! c6 r$ g1.流式套接字(SOCKET_STREAM)* h/ q! t& _; x2 A6 ]
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
8 Y' X! R a6 Z' I" n+ j2.数据报式套接字(SOCKET_DGRAM)
8 b, p( c8 B5 n& J3 Y. V 提供无连接的数据传输服务,不保证可靠性。
+ o9 c: o' K8 s* }6 Z/ C9 I5 I- r3.原始式套接字(SOCKET_RAW)
! y& @% Q$ l( D6 k6 I 该接口允许对较低层次协议,如IP,ICMP直接访问。
% F1 k2 [) T* }$ v% l+ x% A* X5 ^' B
' B0 l& B1 X5 ?" @- `) g二 基本套接字系统调有有如下一些:- m. J3 h/ \8 P2 Q& L( G$ V+ _. ?1 U
创建套接字: socket()
) U5 w/ H; C9 s: n% c* ^7 I 绑定本机端口: bind()
6 d$ a( P- o8 K' \0 W8 C0 g 建立连接: connect(),accept()+ h6 r1 X( d1 r% S% X( G
侦听端口: listen()
0 C, C Q0 { I$ X/ k9 m C 数据传输: send(), recv(); V5 V! O1 a% w7 z/ V" ]* X
输入/输出多路复用: select()5 S4 n+ N# Y4 ?# \* i% f
关闭套接只: closesocket()
5 q+ z% j, W8 w+ { ' Y$ Q9 {; a0 M
三 数据类型" j. g c* O+ ~9 z0 a1 ], G
struct sockaddr4 |# I7 E8 ]- m" o6 L3 i# T
{; g# @' ^% q+ H+ x, q
unsigned short sa_family; //地址族, 一般为AF_INET' G! y5 T' T6 U
char sa_data[14]; //14字节的协议地址" @9 i' A, i) J9 d1 l3 a0 j' D
}
8 d9 L$ x* `8 `
. @* a3 w) c' j+ A3 }9 B4 d struct sockaddr_in1 v6 F: M- I7 i ^6 ?
{1 K- g1 V1 u! d4 t. w
short int sin_family; //地址族$ k, M" Q9 y8 N+ Z- d4 X
unsigned short int sin_port; //端口号
2 i8 B1 f0 R' |$ I% i- S( t struct in_addr in_addr; //ip地址
4 b/ s: o+ I9 Z( c5 z unsigned char sin_zero[8]; //填充2 |4 `1 g1 n% z U
}
* L$ ]: @3 z) l! H, J1 G! G- v7 S4 \; n7 S
四 常用函数3 D, h. d7 x' a$ [ e5 J, c. x, V4 w
1 socket()
$ b5 {8 k8 c8 W2 O. O# `/ Z6 e 头文件: 5 M, R, Z5 v6 q! F" P6 U; Q! N" i" U
#include <sys/types.h>
& H2 @. m- n6 z, T. V& B; g4 e #include <sys/socket.h># r: p& R+ A- f
函数原型:1 }% a& r- ~) ]5 b6 B
int socket(int domain, int type, int protocol) j6 C0 _8 Z) N+ a1 N
domain: 协议类型,一般为AF_INET
8 T4 Y( y+ N9 f; w! @ type: socket类型8 ]1 [2 D2 b. n
protocol:用来指定socket所使用的传输协议编号,通常设为0即可
@# g% u# I8 c' L: m9 Z, {. n4 J6 y
2 bind()3 B: N1 r8 V0 g% U
头文件:9 Q. [0 r3 F: |& }
#include <sys/types.h>+ u Z) E/ r; T- {4 D
#include <sys/socket.h>$ B# T |& t& g. z$ k2 V' N) t1 D
函数原型:/ Q) ^+ R0 b! b+ P; |. N* s8 L
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
: D$ f1 A! Y' u& q8 B sockfd: socket描述符& U1 Q; Y7 s8 [1 p& j- C
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
- f3 v" W! ?" f addrlen:常被设为sizeof(struct sockaddr)
- O$ ~( H. K, |/ j7 q' j' H4 ^
) c# u6 G& M6 C3 K5 [9 r 3 connect()! w) D" m9 b9 x1 D( e
头文件:8 k9 m. j$ ^0 L8 A3 Z( i2 R
#include <sys/types.h> 8 a1 e" E% U, F) p4 M' `* C
#include <sys/socket.h>0 N" |$ {; {) N* S% S
函数原型:* ^: j7 [, E8 Z b) l6 a
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
4 ]2 b* e9 y: V sockfd: 目的服务器的socket描述符. k" k, v }$ j# u, r6 z7 O
serv_addr:包含目的机器ip地址和端口号的指针
/ C/ f5 F( ]- N+ X9 g addrlen:sizeof(struct sockaddr)
; d8 u+ Y) q+ ^" X% N% o1 S
% z b) F9 K' y: {, c0 G 4 listen()1 [3 a$ m1 b0 @9 U
头文件:" J8 v( I( ?& y8 ~8 B, D* j
#include <sys/socket.h>1 w6 @& g1 q T9 C
函数原型:
$ Z3 s% y. a5 u6 e, h int listen(int sockfd, int backlog);9 z% `0 T- H' ~2 u/ m/ s- P
sockfd:socket()系统调用返回的socket描述符
3 G5 O- Z. U- _& b3 W2 L, D+ ^ backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。
. G# y( ^1 E1 B9 O# h
/ ?- L" `- u8 l; O2 P3 k) Z 5 accept()
3 o. x" E' R7 Z" j8 j9 \ 头文件:
/ C$ m& [( X. c# [9 A7 j #include <sys/types.h>
( a, @7 _1 a& W3 D& [1 o #inlcude <sys/socket.h>
* m3 S9 `6 Q( b& s0 n0 g. i& f; _) g 函数原型:* D9 T0 K8 m) G5 V& p, e$ s
int accept(int sockfd, void *addr, int addrlen)
/ O& ]8 {( n: P9 ?, y0 e' L sockfd:是被监听的socket描述符
$ C, o- x/ x& ? addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
% Z) {9 S8 E3 T) _9 q: N addrlen:sizeof(struct sockaddr_in)
( A# T& z6 n0 N" i : t/ }7 u5 M l, O7 g+ {
6 send()1 s3 g( ^( c4 r* t4 |6 B& t
头文件:' |$ _ @' w' H3 a- R
#include <sys/socket.h>% _: K6 A8 ]0 x, Z
函数原型:9 `& t. z0 `2 s C! C1 D
int send(int sockfd, const void *msg, int len, int flags);0 _+ h6 `) M8 |
sockfd:用来传输数据的socket描述符$ m) a; @- x* I" M; B0 g+ m- q
msg:要发送数据的指针
. F3 _% _4 H' H9 a) d flags: 0
. W- L$ b# V; T. m+ h. E 1 p3 j. B3 n3 n' }$ ~' }2 H/ K; w
7 recv()
/ D4 g1 \8 t$ T8 g( S* Y 头文件:9 g6 k% U; l* a7 V
#include <sys/types.h>5 p1 V( @: i' ^) w% C# O/ s
#include <sys/socket.h>0 q' l ~% O7 _
函数原型:
6 I4 G; h0 L7 ^2 T3 E4 z" c1 G4 } int recv(int sockfd, void *buf, int len, unsigned int flags)# J5 M) P: n4 n! ]% a
sockfd:接收数据的socket描述符
: g/ g* o. r- e buf:存放数据的缓冲区
9 H* o! y* A8 V9 C len:缓冲的长度
; o6 R% p$ B& a8 C; e t; O flags:0
* y6 l4 B- J! u$ a( t2 q) D3 H
, H2 x F' d x# _$ V" E3 l" e! p' Q+ T 8 sendto()9 x2 r- q! b4 c7 @
头文件:
& O+ k' D( `* X. k. l: y #include <sys/types.h>
' e& |" T6 Q5 I0 w2 D #include <sys/socket.h>; n! S- o& f0 I% p4 {* K$ u
函数原型:
/ o. N/ O+ q4 O4 p4 @: e. w int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);- s9 `8 \. ^ c9 i* f6 [7 p; q- }9 P
! V8 [) `# s, P$ V$ S
( Z' [. ^$ T5 R; M5 |
9 recvfrom()
- v5 W. s9 B# E5 S2 T 头文件:
4 z! {! M. a9 u' R6 ~ #include <sys/types.h>8 f, P" L7 h1 ~- n1 V0 m
#include <sys/socket.h>
, p }1 z- ^$ v 函数原型:. q% L* L$ e4 L: w8 B
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)
( ]* F, L5 P3 t0 K7 v9 s' J5 h& s5 I, K$ ?3 m# U% U
" d& ^2 K3 H2 B. {
10 read() write()9 `% k# y3 z( V1 \7 r, f" I5 D
int read(int fd, char *buf, int len)
( w3 a( n% f8 h2 {- m9 c7 ~ int write(int fd, char *buf, int len)
) y7 n& G. a- b/ D7 p& k
1 n- D2 c8 e% g2 r 11 shutdown()* g6 u4 u% D- W% l- m4 v7 _( S
close(sockfd)
2 f X9 Z [5 q X9 S0 t int shutdown(int sockfd, int how)% Z+ P4 g# r: 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等)
C' ]9 f6 J0 S; r<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
9 b @0 J5 y& z<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
% y* A! ~+ T$ T O" o4 Y% x3 Q<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
* W! z! c: |% D+ }% ~) p I<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
8 D# ]1 f. e8 i- Z# Z8 U8 K<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等% x6 f; N# g$ \1 T
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件
1 u9 Z o3 B- i" @$ b% T0 j3 h6 n; e: @4 t$ p
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
( O5 F& B% c$ q p" m#include <sys/types.h> A+ Z( n1 I7 _: o
v4 |! z- U1 Y+ L& K e. g7 u6 w8 a
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
T$ E: S) r1 m( c1 ?! ]* w) c#include <poll.h> //poll,pollfd4 h6 k: ^9 V5 x1 p# a
#include <arpa/inet.h> //inet_addr,inet_aton
+ I1 v* m0 F4 ` K9 @& k#include <unistd.h> //read,write
9 P( n( s' x& T% {#include <netdb.h> //gethostbyname
% ~6 ~/ h( O6 Y' `( K4 o" l& C; |2 u- K; v) P0 [: e) i6 z
#include <error.h> //perror
v3 f$ q, p/ p; p# P" {$ W#include <stdio.h>
( {- M# u, S* }& }4 K2 M V#include <errno.h> //errno# ~, r; _3 j I. f" V" t" o
3 ]. L7 u* ?, t6 N ?5 G1 P9 E
#include <string.h> // memset9 S( N& h) n* M& B1 ^
#include <string>
! I+ _% F. P# P#include <iostream>
' a: b$ [4 E2 R& U
9 [/ P' Z6 z0 i, | |