[size=13.3333px]一 三种类型的套接字:1 q6 m8 X1 j j/ J/ v
1.流式套接字(SOCKET_STREAM)
# J" m, P: w9 s% G, ?; B5 |( x 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。1 R1 |$ q; t- E7 L( r6 P8 i/ I( N' @
2.数据报式套接字(SOCKET_DGRAM): U" x9 n* H. H4 \8 V
提供无连接的数据传输服务,不保证可靠性。- R# J0 {2 s# f& T7 {
3.原始式套接字(SOCKET_RAW)/ c0 V' y5 k+ [! H5 I# l3 l7 U$ u
该接口允许对较低层次协议,如IP,ICMP直接访问。- g2 C* H$ m1 E/ }3 h
& D- h0 R W" j. [8 |2 |) b二 基本套接字系统调有有如下一些:( ]- l/ T2 \, W5 w
创建套接字: socket()7 C Q, `7 T$ v) W! }* j2 `6 ?
绑定本机端口: bind()' W: q8 \5 f/ {9 r4 N7 s% T0 T
建立连接: connect(),accept()$ P8 c8 \* \ J0 L7 _' D
侦听端口: listen()0 G( V6 X" z R: p) i) F3 n
数据传输: send(), recv()0 L8 Z" Z/ H/ k; E# H& c
输入/输出多路复用: select()
! |8 E3 P8 w# ?* y: S 关闭套接只: closesocket(), a4 ~9 s8 C m1 ?2 q
9 E! v1 ^% k, z8 |! V) P1 k6 ^三 数据类型
( k p$ j( n* x1 l+ p" T struct sockaddr" L! u. c: A& C
{/ b% a$ J* z; ^$ ^/ o
unsigned short sa_family; //地址族, 一般为AF_INET; D. V6 `5 v2 f9 j
char sa_data[14]; //14字节的协议地址
+ _; o g- H" R2 d( b4 f0 z) p }% A1 k+ L# K7 E
- t# O$ f! ?9 \6 s1 O! n3 V struct sockaddr_in
9 ]$ h8 K- b) p {5 W: `7 u1 s6 P
short int sin_family; //地址族
. j- V0 G+ }4 r7 i unsigned short int sin_port; //端口号 k% h7 R4 ?( ]* a/ C
struct in_addr in_addr; //ip地址, Z9 m. Z) o4 G
unsigned char sin_zero[8]; //填充, N1 u) p. V$ i8 f5 m' b
}, r! c5 f' E Q* [# {& K* }
1 t7 U2 h w" h3 v四 常用函数% A( r9 N. N" Y9 K
1 socket() P, B+ v( ~- B9 k S
头文件:
5 D/ f" K7 B2 q* ?3 H* Z #include <sys/types.h>
8 I% I4 N- @* z. F' }- w #include <sys/socket.h>" [, P# L5 X4 `) ]! ^
函数原型:
2 x: S8 _, k8 O$ w/ f% v2 r int socket(int domain, int type, int protocol)1 [4 K% y. \0 q2 Z/ J
domain: 协议类型,一般为AF_INET! ]" d% A' a8 ^$ \9 h
type: socket类型
. z4 x7 T' f5 L. l2 U9 {4 z7 L protocol:用来指定socket所使用的传输协议编号,通常设为0即可
- Z4 y7 T1 J& i# i0 n4 X' \% Y+ J' l; A' c2 \3 ?, |
2 bind()) M* A: O* |7 W& [+ n" e) _
头文件:- C1 j$ d/ i& E4 \
#include <sys/types.h>9 d M# }' l; \) o- G% `
#include <sys/socket.h>
* s) q a4 c U4 |) J" t 函数原型:) A4 `1 J5 d! @9 D4 H) C
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
; ? n6 V; N8 T3 E. K# {3 G sockfd: socket描述符
# B1 E/ l, @4 L. O5 H- ~ my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针* o3 `8 u+ |/ i8 L' K
addrlen:常被设为sizeof(struct sockaddr)) j n5 f' ~5 W' r: ~- m- L
J2 z7 B+ l5 P% y0 E# P$ h
3 connect()9 A% i* e9 U! b5 z
头文件:
; G7 l( j; ]$ Q0 N: ~& |& r, Y( m+ k R #include <sys/types.h>
: o3 D% q6 d1 I: X$ t #include <sys/socket.h>
/ L! Y. s; d5 @. v w3 k 函数原型:! ~8 h7 n& s- m# `0 b. r4 X
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
% |5 q5 o2 ?# P) T1 L! Q sockfd: 目的服务器的socket描述符
- O) S% S @2 \3 _* X! K serv_addr:包含目的机器ip地址和端口号的指针
5 E. F9 B! ]4 _3 n/ F addrlen:sizeof(struct sockaddr), G8 j0 I1 ?' n1 Q ]
+ p) I( z) D3 _$ W
4 listen(): g" T- a) o: @4 _& Z0 r8 o
头文件:
0 O" z8 e" Z+ e _ t #include <sys/socket.h># N6 A& k% j) H) u$ o
函数原型:* j( s* P ~, `
int listen(int sockfd, int backlog);
8 Q: o2 r0 _ f9 \! v sockfd:socket()系统调用返回的socket描述符. X' q. p6 ~+ V
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。: D2 e! C/ @ |3 X/ ~' M: _
8 ?7 L9 j1 f9 a
5 accept()
" E9 T+ P. M, F2 x( N7 t 头文件:
0 y. ]6 s2 s6 N' X% { #include <sys/types.h>0 z. R# C2 Y2 q% v' a2 r
#inlcude <sys/socket.h>$ f3 |& G, j/ k6 R
函数原型:
- W1 j. B0 i; f H int accept(int sockfd, void *addr, int addrlen)/ z1 Q9 G' }% K7 {% E! ^
sockfd:是被监听的socket描述符) j/ i1 @2 C4 d
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
/ ~0 W n7 ^( X4 P addrlen:sizeof(struct sockaddr_in)( Z7 _5 F% J, K4 w0 u
$ V) W. Y4 {/ U6 ] 6 send()0 f7 r7 P) f8 g. Q$ P% N
头文件:
2 C; o1 B$ K: [ }) t #include <sys/socket.h>, c9 R1 U- R6 f- }! K# U8 M
函数原型:
" g) s, z5 i5 T) D2 ~ int send(int sockfd, const void *msg, int len, int flags);
" h' e4 ]7 Y+ L$ s" { sockfd:用来传输数据的socket描述符
) v3 r$ v0 \2 m+ w" B, |8 i msg:要发送数据的指针
* r1 G& |# H0 Y$ B# q( u flags: 0
8 O. l! G1 ~7 Q. s7 R+ B
9 t' U" s# V! z1 ^$ H- n" d4 |/ x. B( z 7 recv()
0 y8 u8 x3 a9 Y4 r! L3 J 头文件:, Q1 E- |: s/ w3 A3 T: D* z0 n
#include <sys/types.h>
6 w4 k, n* y. z #include <sys/socket.h> H$ f* b* M% Y! S: k) z
函数原型:
+ s" z- ^+ s* n int recv(int sockfd, void *buf, int len, unsigned int flags)! ^; ^6 W/ O) {1 U
sockfd:接收数据的socket描述符5 `: f+ d5 `; h3 |
buf:存放数据的缓冲区
+ e/ E4 W; w# n- C5 c; |0 F4 c( l/ Q- T len:缓冲的长度: K% r3 E9 Y l$ O
flags:0
# ]$ V2 D" v4 ]
% ^( ~! r& ?/ p5 s* l; A0 B 8 sendto()
% a$ @ P! K! Q7 C7 V, \ 头文件:
- g# ?* ?# U; {+ L6 g1 B #include <sys/types.h>7 Y; ~* X& L$ Q9 h O: c2 C( C
#include <sys/socket.h>
! ?5 m$ L, O$ \+ e 函数原型:, n- Q! }: p. n# R
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
8 v( b+ ~7 r6 ]0 N% E! S" k8 `# p. v / X1 ?1 q3 t/ A
# A- \0 h6 X, _" A/ G
9 recvfrom()- B; p; n; r0 q W# g
头文件:
2 Z2 ~! j$ l; U8 J9 L4 b) ~ #include <sys/types.h>1 Y9 ]- m8 F; u M5 o. C% k
#include <sys/socket.h>" i3 A! K: g7 ^! w4 ~! [8 S
函数原型:+ D- M1 |' R, r7 W
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)
2 d% S/ p9 O1 T9 Z0 l- R1 y( J
6 T( ^, E' n+ K; \, k 4 o, n/ G/ ]5 G
10 read() write()
# [! a6 L. U7 I: r; u* j int read(int fd, char *buf, int len)
9 ~+ i s7 ^5 S$ f9 h+ [( F int write(int fd, char *buf, int len)
0 l0 j" J# k+ Y* u" p: { 8 |) z9 ]; @- R: I0 s# V. r
11 shutdown()
1 j( W4 i" j( i b: C4 }! w close(sockfd)
* O3 |! w, i* h& L5 R int shutdown(int sockfd, int how)4 D- a" o4 |. | O$ E* }! d
----------------------------------- [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等)
# F; X% a$ u8 G$ s" A<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
$ Y( M5 }( O {7 |& S9 ]# c9 d<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()0 u' A# i0 \# e: Y/ h# @; i
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等) C+ A8 c6 R8 n
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
2 T* O+ A3 I2 e& g h Y<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等9 R# n U' ~4 A% t6 U/ P: |8 `
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件3 c+ K/ I6 f* L" b
% G5 u$ _% X" H- c- `* f[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等# @/ r2 u+ K6 b C
#include <sys/types.h>
4 x+ _. N# \2 `" T) U
$ T. Y: ^7 \4 Z) L#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons: r: L. H, h! g/ A/ S
#include <poll.h> //poll,pollfd" Z# P. P! @- e5 ]
#include <arpa/inet.h> //inet_addr,inet_aton
! c; ]( c" N( [3 u/ |- C#include <unistd.h> //read,write
8 F3 ^5 ^2 u N8 X. O. P* X9 H8 F#include <netdb.h> //gethostbyname6 z* I4 P4 Q" I$ d5 o g5 v% |- y6 B
. Y/ ^4 d" k& g# M/ H#include <error.h> //perror# |9 i- ~$ p- N( ]- o, k
#include <stdio.h>
5 s$ J; \5 e7 r, y#include <errno.h> //errno
# [; {; v- l7 [6 x4 U- ?% M$ J, Q P2 {& M* Y1 \5 _) V
#include <string.h> // memset. f/ a& c }9 X4 e( s% J6 X
#include <string>
; N, W4 W# l5 `; i; e% N#include <iostream>: c$ H& ~' t. U% f. @3 l2 @/ B! ~) A
- {& T& k+ F6 w( N; q* _4 X |