[size=13.3333px]一 三种类型的套接字:
9 f; H. J+ l+ Z1.流式套接字(SOCKET_STREAM)
8 H& Q8 S! _0 }$ y0 K) s3 W 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
0 l# [7 K" T& X% S! G2.数据报式套接字(SOCKET_DGRAM)4 o [( r+ J" O4 q
提供无连接的数据传输服务,不保证可靠性。3 B1 I1 y$ S* N, E
3.原始式套接字(SOCKET_RAW)& v6 E0 K) g8 J4 @9 T
该接口允许对较低层次协议,如IP,ICMP直接访问。
. G* [5 T3 w0 ~, Y* T' }; C/ z1 M b% h9 P! V. g1 I: W
二 基本套接字系统调有有如下一些:
4 e% D7 r% G0 h7 l* C. ] 创建套接字: socket()
/ G2 h, m3 s: j4 m& B 绑定本机端口: bind()* t4 z# Y( ]* ]3 H8 ?1 w
建立连接: connect(),accept()+ h4 [ J _; S9 T; M+ E2 O; {
侦听端口: listen()- k% d0 J, S# Q. I) a. X z9 Z4 z& W
数据传输: send(), recv()
1 P, ]' k# V0 S8 O( X& Q! q 输入/输出多路复用: select()
; q# h- K6 w( [, ?* ? 关闭套接只: closesocket()( d; z5 K7 V" k0 C, R5 \
$ D, _2 H4 i. a8 Z
三 数据类型% E, Y9 ]3 x* E5 Y+ g( J8 E3 d
struct sockaddr* E' d( w' L9 |0 k
{
+ W$ `# v L' G. W" m. ^+ R4 D$ z) I unsigned short sa_family; //地址族, 一般为AF_INET2 C. k) S- V' g
char sa_data[14]; //14字节的协议地址6 O B) x9 l% p% R- z
}- r) {& i0 O) W
$ w1 H; D- ^0 E: N8 C3 f9 r
struct sockaddr_in
& }% p* Q6 d9 p1 Q( z: P% T {
G) B; o$ i d3 b, d' @' h' r" J short int sin_family; //地址族+ @! o2 Q t& o/ y, m
unsigned short int sin_port; //端口号% \: M: {' k& y4 C" m6 G3 | s
struct in_addr in_addr; //ip地址
4 _! _7 x& ~9 c; q* ]& T unsigned char sin_zero[8]; //填充3 T6 C7 U K8 H _$ l( {
}+ B+ h! w) e7 p7 d9 `$ s. ^
/ F6 u4 N* N: ~; K四 常用函数
9 N6 ^8 {2 ?" f L. ~ 1 socket()! @& Y0 g* b4 G7 x3 O' v A
头文件:
$ M5 p4 i" y& ~/ y: i3 f7 J; j #include <sys/types.h>
' ^0 A! y) v+ B$ ~# |' m9 o #include <sys/socket.h>
; x- z0 X' s. @3 R/ U* Z% X 函数原型:
# @4 k% J. G( r' f3 Z int socket(int domain, int type, int protocol)( O( L) C2 z2 C/ ]
domain: 协议类型,一般为AF_INET8 p( V9 \1 }% B0 u3 f4 O, N
type: socket类型) `3 w( m# F# S1 O6 F: }6 p; G- S
protocol:用来指定socket所使用的传输协议编号,通常设为0即可- I2 G$ X) j. x3 t2 \: G( |, ~( F
$ h0 @1 s0 C3 z8 i4 s 2 bind()- b$ D' T# q h6 f! y( R
头文件:5 G& {- B( b, V! s
#include <sys/types.h>
" n3 h$ x# n5 a6 c5 L } #include <sys/socket.h> D2 q0 |1 \' b+ y
函数原型:4 P5 `4 S0 a4 M+ a; I/ W# A4 D: ?
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
; ?. k. ]) d% U sockfd: socket描述符$ r6 i2 F: @; p, `# A
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
/ [7 @) j& e `" s0 a" A3 D addrlen:常被设为sizeof(struct sockaddr)4 Z& j1 h# g9 [/ P
8 c2 b" T2 P4 t* a: g 3 connect()
$ x( @5 L y. l 头文件:2 x1 S1 ^! \: R* q+ h( s6 i# t
#include <sys/types.h> $ F2 {6 e& z" w( y) M2 s. x1 m
#include <sys/socket.h>* B% N4 F9 d0 D7 N
函数原型:8 H- t' m" Z2 }. ~- I
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
8 W4 R9 H0 K9 E& d; p ~ sockfd: 目的服务器的socket描述符4 W- @, R% h& [9 n3 u
serv_addr:包含目的机器ip地址和端口号的指针
1 J7 f, T8 \8 K- ]- A addrlen:sizeof(struct sockaddr)
, D3 u- m3 g9 E7 [/ I# n% L
$ Y4 P( C8 u0 f5 b. R5 o' J2 n9 f; z 4 listen()6 c# W; t: `1 t4 F2 s
头文件:
3 a1 `# r4 {4 e* @4 q9 U2 i( S #include <sys/socket.h>) ]$ c# h t8 E, Y% T
函数原型:
0 D2 k* G, Q/ ?$ `6 a8 G int listen(int sockfd, int backlog);2 L& i1 K; V' k. q! H6 K/ `0 k
sockfd:socket()系统调用返回的socket描述符4 n1 m9 P9 Y* @4 ?9 q L1 n
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。
, O# r& v+ g- |5 y& @' A* c: \# ^3 ^- _8 S0 | S, l
5 accept()
2 s9 H. U* ~) }8 B8 ~* Y+ Z9 P( z 头文件: 7 F5 {8 {' k# w# ]1 l8 O+ _
#include <sys/types.h>" ~$ ~9 q4 O& a) Y: e# w
#inlcude <sys/socket.h>
+ n& O+ c. j) P* r D5 B 函数原型:- Z# y F$ S$ a' Q6 v0 r |/ J6 j. ]
int accept(int sockfd, void *addr, int addrlen)4 o6 S3 H; S$ J, _ O& d
sockfd:是被监听的socket描述符
; o8 M$ p! V/ I( w- q4 e addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息" o @; q0 u/ B, I6 `; A
addrlen:sizeof(struct sockaddr_in), a% }& w9 ? U% a. U% c
% ?7 X. ~5 }/ Y0 ~7 d! c
6 send()' X7 Q- ]2 j2 W/ k8 z4 r/ S/ O# d
头文件:# [2 f& n# j& k7 e' E
#include <sys/socket.h>
( d, }! e% m4 M! Z3 G 函数原型:% L: G2 x( a" p2 u7 Z
int send(int sockfd, const void *msg, int len, int flags);9 Y1 s- _. z+ v( o l; T, |3 z
sockfd:用来传输数据的socket描述符
/ {2 B! t2 Q) ]1 {/ v6 C msg:要发送数据的指针
# Z- i& g) N7 C+ s5 b6 w! B) F4 J flags: 0
' ^9 H. z1 i% r% d 2 p8 O6 o2 O8 _ w/ I7 j
7 recv()! Z/ C6 h! u& u& `! s
头文件:
; T/ g w" u& ^3 B/ ` #include <sys/types.h>
- V0 _7 G8 V4 j4 R) U #include <sys/socket.h>; i4 Y9 l3 J$ i6 h
函数原型:
# V8 X9 z4 z! ? int recv(int sockfd, void *buf, int len, unsigned int flags)
* I9 F; R+ J& a& ^ sockfd:接收数据的socket描述符1 i% i* S% S! j7 T
buf:存放数据的缓冲区
! [ G; J! o, h( G( r$ B len:缓冲的长度) g. |. [' L: y# H
flags:0
* u6 W4 ], ~" F- F% w% N
; b! j' N3 E+ y# X9 M; B c' K: y 8 sendto()9 v2 ^4 B$ M/ P2 t3 p+ f( c. @ X
头文件:' s" i( j f, Q& Q
#include <sys/types.h>; [. f7 c; E0 V5 k8 x f) F! ~
#include <sys/socket.h>
J" r3 F& k2 F: A8 Y 函数原型:7 J1 H( m& L$ _8 a
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
$ N. n9 o) x- K) C : A# J+ t* @ N9 O( A
( q U% m/ \4 _
9 recvfrom()
1 S( k" x; y0 c! ^6 s% Q 头文件:
" p! ] l: K( D+ i #include <sys/types.h>
/ ~6 |$ i' b; L3 e6 M0 O8 J #include <sys/socket.h>
' R+ ?3 p: y$ `7 Y 函数原型:. S" g) y' v' h' k
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)9 x* L% R$ t( t A$ ?- S; C
5 N4 u" u- F* N) c- }* N$ n4 m
7 n1 R# s" N, r2 f3 p 10 read() write()
& }" X: v" K# Z4 G( ] int read(int fd, char *buf, int len)
. F6 s* N* l" |5 r8 I- c int write(int fd, char *buf, int len)$ L: p" q0 S; Q
' E0 B; ? D) \# Y1 c 11 shutdown()3 v$ W& N1 Z; z" {7 v U+ V
close(sockfd)
+ v# N! S8 v; c l/ [ int shutdown(int sockfd, int how)1 {3 B% D, n# C2 K
----------------------------------- [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等)
3 R& Z/ a- o+ J4 r<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
- S6 @4 U& s7 i- T- F0 ?2 u* t<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
7 N9 X$ `9 _/ a& d$ ~4 {7 X. W<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等0 _4 B, j2 H* ~; a, p$ ]6 B: J
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
?* y% N9 U7 f2 Y3 T4 K/ I<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
) U1 R# [- I0 k2 @/ @- S6 q<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件
- R; H* I2 E6 x e% E: \5 r/ V* E V
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等8 _& a. r. [- ~. T( R
#include <sys/types.h> 7 x5 e/ w; z; l$ [: |- x
2 x# p) ], m6 U" M5 z! @#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons" q. n' N; H* I0 a9 |" V
#include <poll.h> //poll,pollfd1 p: [. s5 @- @: A) B
#include <arpa/inet.h> //inet_addr,inet_aton, |4 u0 I# G3 l Y3 O+ A/ [
#include <unistd.h> //read,write' `) e; x; b, z" |3 `! ?
#include <netdb.h> //gethostbyname
3 N- P& `2 a. D3 j: [- I+ R% H. i7 g0 H* m. A
#include <error.h> //perror
1 \" I: J& l2 L: q/ A+ s ^4 H4 I$ q#include <stdio.h>
( G( ]4 {9 T9 s#include <errno.h> //errno
9 N+ ^9 C# N' ^" o
! k: ^& O% C% o; b#include <string.h> // memset
- h# j; r- c- |, b. C3 D; m X9 ]#include <string>
& w* x& H& d5 l4 I#include <iostream>; v9 Q* F* Z( S# C. W; w3 H* [
: }! t, g* g& T6 [1 _/ g |