[size=13.3333px]一 三种类型的套接字:
2 X( ?" b' K; U" N- V: _1.流式套接字(SOCKET_STREAM)( p" |- D. D- ]& O* T# G
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
h0 V1 {4 P9 N) A2.数据报式套接字(SOCKET_DGRAM)! @$ K: F' O6 X7 r% x
提供无连接的数据传输服务,不保证可靠性。7 M; i9 l# B! p
3.原始式套接字(SOCKET_RAW)
& r; F1 B# ?' C) Y 该接口允许对较低层次协议,如IP,ICMP直接访问。! h" j0 ?- F2 C# S/ L+ ^4 u
, u7 }* m$ V \ D6 m
二 基本套接字系统调有有如下一些:
- i/ k1 M4 ^: ~' h 创建套接字: socket()' N; F# a H, G/ k
绑定本机端口: bind()
. l, D, Y' y5 K- Q6 [& k; { 建立连接: connect(),accept()
& A" C1 Y& I2 x1 Z7 q, J6 W- R 侦听端口: listen()6 G9 l( F5 j! `6 G B
数据传输: send(), recv()
% P/ }5 m8 K+ _9 u, I, X9 w. Z 输入/输出多路复用: select()
8 `! D% B6 M. K5 q 关闭套接只: closesocket()) y" S! A; @) D3 a6 a, W. p
2 T9 c/ L2 L7 Y三 数据类型* f6 Y7 J' Z. `9 i w6 x" r5 F# J0 M
struct sockaddr2 z" }2 T4 {& F1 v: Z& H: t
{$ s; a6 J" t* u: ^0 }
unsigned short sa_family; //地址族, 一般为AF_INET
5 C5 i" X" ^4 H) {$ s4 t- L* g char sa_data[14]; //14字节的协议地址
1 u) \, t6 D) ]4 B" l; P1 \ }
4 V6 v; i4 l; c/ M5 k+ X. P9 |) }! s9 E5 |3 y, [. G4 |3 B
struct sockaddr_in$ P8 Q' @3 f+ Z" ] O' J" t: g
{
( j8 h+ C: b# a! e short int sin_family; //地址族% [$ i+ r2 c7 v7 a1 L
unsigned short int sin_port; //端口号8 h! \3 [% a# Z: n, e |/ T+ E
struct in_addr in_addr; //ip地址, Y: p/ D# b9 V- D: f
unsigned char sin_zero[8]; //填充0 I% K4 w( N+ u: ?
}; O9 h5 q/ d( J( N2 y0 n+ B
" x" v4 i* ~* e( f
四 常用函数% U( F9 G) o2 N d5 z, o
1 socket()
$ J- x8 [9 K) f c9 ? 头文件:
' @ m- b& d8 M7 B1 M6 \ #include <sys/types.h>. d9 t4 _: \ `$ W
#include <sys/socket.h>2 A& j9 k1 w+ Z
函数原型:
5 U: C5 Q" ?# i int socket(int domain, int type, int protocol)0 j& l6 A4 S) b# F
domain: 协议类型,一般为AF_INET/ k8 s$ L" T" `: v' R5 N; @
type: socket类型
9 }& P, ~ `! X! z$ q t- E8 b protocol:用来指定socket所使用的传输协议编号,通常设为0即可' F" y# F' S6 q( m8 R" ^$ c: |0 C
- Z" E& X9 o6 h5 Y& L! P 2 bind()
/ f2 j7 H3 d3 u8 f 头文件:2 V$ J* j# m7 W: D; |
#include <sys/types.h>3 o( V1 y% J/ C: b) |2 v
#include <sys/socket.h>$ k1 e, E& T' V2 @' H
函数原型:
2 X1 \: d. L6 N K int bind(int sockfd, struct sockaddr *my_addr, int addrlen)2 _; ?4 z, p+ m6 q8 Y" W
sockfd: socket描述符
$ i9 v& ]+ Y x my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
, f: w2 p. w v/ K+ l$ H( \( j addrlen:常被设为sizeof(struct sockaddr)
/ f6 u0 F' I. L0 G% L1 I8 i" B0 _* A, K4 N6 c
3 connect()# j/ P/ d: p `0 T. n6 p
头文件:
3 ?' o# g! N# d# C- |$ @, ^ #include <sys/types.h>
% K8 _4 z5 Z3 Y- d #include <sys/socket.h>* M: K$ b0 B6 f* D/ T5 _
函数原型:! Q+ l2 Y5 e3 ~4 n: e8 y
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen) Q3 q Y5 Z4 \0 ? i0 H8 I, p3 v
sockfd: 目的服务器的socket描述符1 n S2 y* E! y8 |# ?% e. S8 T/ m
serv_addr:包含目的机器ip地址和端口号的指针9 K0 X9 N' R! Y/ @# L- ]
addrlen:sizeof(struct sockaddr)
) `" z, S+ a/ F! y; y1 X& a4 k
9 `5 a3 V8 V! }: h6 u6 _ 4 listen()
+ _/ d: N# ]9 V9 V 头文件:; f3 s7 d7 s$ ^3 e8 R* U% H
#include <sys/socket.h>6 b% _: U1 Y5 Y4 o: ^% q0 T) E
函数原型:
) C( i8 j- _5 p6 U8 |2 Z int listen(int sockfd, int backlog);* U- Q; {/ T q$ V! y5 ^ |9 J4 ]- G
sockfd:socket()系统调用返回的socket描述符
% x- V; n' Q2 I* \& T backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。
9 d# I$ i/ J# k2 o: w8 G( m, O
2 _" U, k) Z" z1 U, C 5 accept()) i' C8 P8 J) S. ]% o
头文件: 1 J4 ]" _# Q6 E& o! E' ~* r& Z0 [
#include <sys/types.h>
' j2 G3 R. ]7 } #inlcude <sys/socket.h>
8 n; \# L! o- V/ d: z 函数原型:4 y$ F5 U% k3 o) s
int accept(int sockfd, void *addr, int addrlen)2 I3 j; f, J' q; S/ ~' L, S: i
sockfd:是被监听的socket描述符! D. Z ]9 ~4 o7 l; _6 X
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息6 C4 I, M8 S% I4 {' }7 d5 _/ E
addrlen:sizeof(struct sockaddr_in)' k1 \4 `8 [# |0 T5 \
. |. w o, O7 E! Q# { 6 send()
; d: F: ~0 P! F* b, w- \: W0 D 头文件:/ U3 O# o/ F# h" w
#include <sys/socket.h>
6 ~ J% b1 d/ ~$ g7 A% m 函数原型:
2 q7 {6 C. Y) y+ p" t# @ int send(int sockfd, const void *msg, int len, int flags);
! t# S# Y* \9 ?5 I6 e5 m sockfd:用来传输数据的socket描述符
0 ^( O4 D$ y1 s3 T4 g z& y- | msg:要发送数据的指针
/ m8 B( }: N* I3 s! v3 t flags: 0( Z% ]$ b% J, w# B# M% J
f! {7 A8 S" E2 M& H% e( p7 o
7 recv()+ n3 }! z0 ?5 W
头文件:' G" \+ F! w, o4 n7 a |
#include <sys/types.h># f5 P {+ p7 t2 S
#include <sys/socket.h> `8 t$ S j: H: ? u. b1 w* J
函数原型:- |! z( Y- O% n' Y$ ?: S
int recv(int sockfd, void *buf, int len, unsigned int flags)
$ w5 T, h# D# w( k/ C$ r sockfd:接收数据的socket描述符
$ |" u5 T3 z+ b5 g1 \' i buf:存放数据的缓冲区* @7 {& z5 e2 m0 [, n
len:缓冲的长度* `! X$ J7 x) g$ p9 a" b, i. a N( }
flags:0# s: v1 A% t8 x/ R- U. d
/ X% Z' {* r% ^5 z9 L( }) H
8 sendto(): l8 o0 k* ?8 T- n5 M
头文件:$ N! x; F0 U& j2 O- s& k3 \
#include <sys/types.h>! t# i( m& Y- Q) G; Y
#include <sys/socket.h>/ j) Q& D' x2 \. s& G
函数原型:+ N, f7 ]4 D* Y' H8 l" `: ~
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
! |& t" Y, Y' [/ Y' z6 n
% P4 W6 t- ]- b! v; }+ y, [ 8 C% T( I! _2 w" ~% t" a
9 recvfrom()
: o8 r2 B& R6 d 头文件:
$ o8 j; x3 p# v3 G #include <sys/types.h>
: f# L; Z, a8 y3 e #include <sys/socket.h>& M* o7 z% \1 k; W, r
函数原型:+ {! C" O ^% E) ^/ {1 J
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)
0 J0 x: y1 r3 |# ?+ ?
# w+ k+ e. ^ b+ `8 z
& p( c( n+ G% d. c4 b$ W 10 read() write()
* K# G$ u/ L4 v. E, X5 A int read(int fd, char *buf, int len)
0 |) h* l3 j- H2 P/ H int write(int fd, char *buf, int len)6 i7 @2 H! ~# i m% M
1 G. G. { l+ c# ^
11 shutdown()% q2 K, h3 A/ M+ [
close(sockfd)
. d- @4 y- Q. J1 X int shutdown(int sockfd, int how)
7 P! ~3 R( r+ i+ C8 g I----------------------------------- [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等)
9 f: D* D" \5 {8 r9 e<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
7 S: x5 a; ?9 ]6 S1 [9 X7 J, K<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
5 r R; z* W7 e0 J' p$ @<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
" Y2 M) h: m) V5 S* a2 s& H5 t/ Q7 O<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等" j- }% x) q+ c! L: N: N5 u2 O
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等, |$ R {; I8 {: p U6 r, d% e# u9 S
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件
1 j0 _& o* D' H I
8 R9 _) `( c$ j$ f4 H: L4 A- p[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等+ V, D* c/ h' a8 G3 d+ w" s+ ^
#include <sys/types.h> ' U' y' k/ ~) R6 o
) k( w/ Z( W! b0 j#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
8 b! H% S- R9 ?+ W" A* Z) e#include <poll.h> //poll,pollfd. V% ^3 m& j- U# {- K9 X% S" K* i
#include <arpa/inet.h> //inet_addr,inet_aton1 p5 u1 ^8 ?: O: a, C0 {" j
#include <unistd.h> //read,write/ f7 s1 i7 q0 C, [4 L# w) k8 V! m
#include <netdb.h> //gethostbyname
h* E6 S3 I* k! p7 T) `8 p9 g+ k; w& D7 N C3 @ r
#include <error.h> //perror# S! o% ]2 F! |% T% \
#include <stdio.h>
) D- A e9 @. B#include <errno.h> //errno. b& t* V4 R W) ^
! ^1 ?' ^: {) l3 U6 c) | U
#include <string.h> // memset
G% B. \( G3 P7 r8 u#include <string>
5 Y( \7 Y3 \+ v& e: ~#include <iostream>
H0 z2 ~% _, B( P" _* b/ E7 Z: d, G
% B7 l/ a: x4 Y; s7 ^" Q, t |