[size=13.3333px]一 三种类型的套接字:2 Y! p8 c; B6 P- k2 W! `
1.流式套接字(SOCKET_STREAM)2 S# u& R* A9 R6 v: y: r7 D8 p
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。( O) n/ m+ c, |* o* h0 c2 H
2.数据报式套接字(SOCKET_DGRAM)* e8 { \9 j: J# O. ~/ H1 A# d
提供无连接的数据传输服务,不保证可靠性。5 W4 M) _3 B: X9 c! o
3.原始式套接字(SOCKET_RAW) ]$ T0 v5 P) ^' H5 d
该接口允许对较低层次协议,如IP,ICMP直接访问。
5 Z% B0 |2 ^' g- x" T" b( E; A
3 j9 u. @- E: ?( K- c二 基本套接字系统调有有如下一些:
, M2 K9 v- N' Z7 Q 创建套接字: socket()5 \' a1 [( s/ v) s3 @: S. k7 @
绑定本机端口: bind()
1 t7 f, l# ]& y% ?8 I8 V. Z e 建立连接: connect(),accept()# s! \& [" r( T" {8 L4 O2 C
侦听端口: listen()7 z- f+ t4 J% ^ z
数据传输: send(), recv()
& X. Z0 l% e, s% [ 输入/输出多路复用: select()0 A$ C! F4 P5 B$ j
关闭套接只: closesocket()5 u+ }4 n/ D% q$ z' f$ ]
& n5 z! K: t8 D& S2 S3 ?三 数据类型
: ]8 A7 a5 [( o4 b. T# \/ } struct sockaddr
; C! ]8 m1 M& t( v {
3 g8 P( C' O- ? j: q unsigned short sa_family; //地址族, 一般为AF_INET
8 ?8 P1 n) g8 \8 v5 |( R char sa_data[14]; //14字节的协议地址# t0 F4 r2 x4 x$ a
}
; r- m. r! H+ f4 N
2 a, ~ n i8 [" E struct sockaddr_in4 S/ |2 i" M# |" n7 G6 E
{: {3 b* a+ G; C
short int sin_family; //地址族: Y M9 X/ c+ Q' g! |- B& X' S
unsigned short int sin_port; //端口号( a# t1 Q" f: p; o* p
struct in_addr in_addr; //ip地址
4 I3 C( ?6 C: e, A unsigned char sin_zero[8]; //填充* N, p# f5 o6 W9 r
}
: q0 |, R0 I* f8 Y* @) `/ P+ Y @9 T' }: y0 w: [
四 常用函数8 E3 o' W \$ k. R
1 socket()
( b- Q1 ? {& n _1 V8 j! l N1 Z 头文件:
0 i0 o, S( p' s p, x #include <sys/types.h>
* v, ~- s h8 p& i #include <sys/socket.h>) W8 B6 D8 j& _; n1 }1 T
函数原型:
3 ]' ~! H0 F) K. }0 k# L int socket(int domain, int type, int protocol)9 ]! F {* q( l1 {5 d" ~8 U
domain: 协议类型,一般为AF_INET6 L$ B4 \1 [$ N
type: socket类型
5 G* ?+ M+ j, b' t) w protocol:用来指定socket所使用的传输协议编号,通常设为0即可$ n2 r- C5 @6 E! ]& i
; ~; B. p' Q6 H, g2 t$ i! |9 {6 n
2 bind()
! F$ S& `5 S; }- D3 O# a 头文件:
/ ?, z, F1 x% R #include <sys/types.h>2 y* y+ P# V: w* G X+ w( y
#include <sys/socket.h>! r; f, s6 M. m7 J* z5 k g
函数原型:
1 C" l. K1 @6 ~% H int bind(int sockfd, struct sockaddr *my_addr, int addrlen)7 e! U* |7 C. i+ `' F m5 l
sockfd: socket描述符- C h8 y8 a5 G4 S, M
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针* C3 s& _$ j B) w2 I
addrlen:常被设为sizeof(struct sockaddr)
3 Y O5 z1 m! M/ k, K* ?* a2 m, ^2 V4 Z4 C m1 N
3 connect()
+ L! y+ {7 X7 c6 e7 I2 T 头文件:
' d& @8 w. @6 r #include <sys/types.h>
0 _+ \# x# a. t2 `4 x4 { #include <sys/socket.h>& y: e7 w4 A& o( G5 U" ?0 p
函数原型:
: @( r9 X2 K8 i( e int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
3 |* ^) w( K5 Q" V/ }8 q9 K sockfd: 目的服务器的socket描述符, S8 k8 y, J/ {0 x
serv_addr:包含目的机器ip地址和端口号的指针$ G S# F7 R: c4 ]5 z) ]! o( l
addrlen:sizeof(struct sockaddr)6 x9 x) J' g# ?$ e, s1 q+ e5 j
; a+ H* |0 w; G; l7 n5 F 4 listen()" ~! p- v% c: ^% g6 E, j" n
头文件:! G% g) g2 D: b1 k/ u ]
#include <sys/socket.h>
# m+ r: v M0 Z- q$ J9 W 函数原型:
1 B; \8 l# f. F, m int listen(int sockfd, int backlog);+ e" f9 o8 S+ z! u5 {- f0 {
sockfd:socket()系统调用返回的socket描述符
$ W. {, i6 r/ n! ~7 }" l backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。5 z- S( u- O2 A( V' X$ r
; a. m' G( Z" J y' \( z l 5 accept()
0 l6 T0 V6 T, K* N! b- D! p5 w, d& y/ h 头文件:
/ d, n0 y' M+ m0 s8 D* U" o #include <sys/types.h>/ \, i# L; J/ M2 N7 L( Q
#inlcude <sys/socket.h>/ a0 v. M% C R1 c* N
函数原型:
$ M8 n( r/ n% h$ s2 C int accept(int sockfd, void *addr, int addrlen)
) x# A5 h0 T5 U) Y3 u3 N sockfd:是被监听的socket描述符* s+ L" J) k- |2 M1 k. i
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
3 I: O" c, v) I7 R7 F" y addrlen:sizeof(struct sockaddr_in); u9 e# `1 o& {. w5 V. B
- F: f5 r4 q3 o+ J5 a$ C0 W 6 send()
& N6 }3 ]' [/ g |- Z 头文件:5 M# G) [* _% n( l- @8 S; [, i3 l
#include <sys/socket.h>
7 Q8 u- P0 U* x6 q 函数原型:
* x/ ]& L9 X t8 d, P) p, t# y int send(int sockfd, const void *msg, int len, int flags);+ X" [7 s; M9 f( {& `
sockfd:用来传输数据的socket描述符2 K0 L E4 n5 U
msg:要发送数据的指针 $ z% X% ]8 {2 R8 z! U) B
flags: 0
5 q% z) W% [ n4 q: d
E% X4 `. j5 {, p" V/ @2 v% a$ q6 u 7 recv()
$ Y A: H9 S8 i1 p 头文件:
6 m! b: b; Y) y #include <sys/types.h>
* i" m6 c- W6 k$ i #include <sys/socket.h>
; P! U: S! S) F f 函数原型:
" N! v8 p. N4 x a int recv(int sockfd, void *buf, int len, unsigned int flags)
# q8 x1 A2 V6 Z8 a6 |6 {/ n sockfd:接收数据的socket描述符1 C( I* k+ e# h
buf:存放数据的缓冲区4 h* i+ k* @. P! H7 Q9 G x! m
len:缓冲的长度
3 g2 r( S% @2 V flags:0
% G& B. H9 [4 u7 |
8 v+ J: C. O3 x3 b 8 sendto(). ^/ a. b' D3 \8 Z
头文件:, p0 y _# D+ N, o- @" X6 u. a
#include <sys/types.h>( f* Q7 s9 G2 i) p
#include <sys/socket.h>
y5 l* x7 ^$ p+ I: k r1 q( z4 F 函数原型:- P, _+ u. p& l0 o# @6 p _
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);, k0 ~; X. c! }. ?, |
) W0 C7 \2 K1 f
7 j2 B" X i; P3 z" J 9 recvfrom() s- Z# a) n9 D, A
头文件:
8 w! i/ P; g0 Q t, L( @) I #include <sys/types.h>6 h5 [9 A) f7 r) Q8 P1 L+ p
#include <sys/socket.h>
2 |6 G9 y+ f# U: v. S 函数原型:( j4 B5 u$ V$ B5 s# q+ ]8 T+ v+ t
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)
* D9 p8 z$ A; m0 R/ \1 g( B
! D. f7 h% `2 o8 U. e% ^* f* F
, A) u/ F5 Q% Y& c8 I: H* [ 10 read() write()$ d( b4 D: F# @- V
int read(int fd, char *buf, int len)4 Q5 F4 \6 D8 {6 L3 Z- c$ B% s! ^0 u
int write(int fd, char *buf, int len)6 z [8 H) k9 I. }5 e4 S6 j
* E6 ^$ L6 s# v; R
11 shutdown()
. J+ Z5 Y5 ? S {9 g: F close(sockfd)4 r. j F: r3 B9 M
int shutdown(int sockfd, int how)1 Q; f4 [6 }: S- h
----------------------------------- [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等) ; b: o# a0 r' ~3 w
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等+ K1 D" k$ s4 m" i# H+ ?0 H* u
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()' i- ]# F- C- {
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等: e2 J; s, A# n) l2 y
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等& q2 K7 _, f* J
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等9 v9 ^! u( v0 i% b) t2 g
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件- U- [6 w9 q7 h0 o0 H7 r# d7 B
6 B/ r! q. b S: x
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等 t; \. c2 R5 l# M9 N
#include <sys/types.h>
, L2 d. i9 E6 t' q, D' H, a! V p8 L) f1 _' I; V
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
/ y7 @9 C D' r S% m- I#include <poll.h> //poll,pollfd1 U! l$ H8 b r# j* q
#include <arpa/inet.h> //inet_addr,inet_aton
! S/ ?9 Q8 Z$ P2 s+ L#include <unistd.h> //read,write
/ G6 A1 I$ i! `5 g& [#include <netdb.h> //gethostbyname
/ P3 ?% _4 S9 a: E$ P4 {2 z% a, p! m) \9 X8 N" H
#include <error.h> //perror
& [# j9 P# Q' _#include <stdio.h>4 F- n' p' }8 y3 f; K
#include <errno.h> //errno
2 c0 D! D. E0 R
/ w% r9 Z) Q: J& B#include <string.h> // memset3 D; M) |* c1 Q; D. y! R% d
#include <string>% s+ m, M% y" T) D
#include <iostream>5 G6 m/ ~6 G% O9 B7 \
1 r: h6 O I9 P/ K; c" C, o+ s
|