|
[size=13.3333px]一 三种类型的套接字:
8 D* E& @9 _- g+ N+ ]8 M* N' A1.流式套接字(SOCKET_STREAM): z2 L: |0 q2 C$ L. Z/ S5 C
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。0 t g* Z _6 x9 A" a1 l
2.数据报式套接字(SOCKET_DGRAM). P: w+ s9 N1 X5 C* X7 E9 F0 c3 L
提供无连接的数据传输服务,不保证可靠性。
+ C. l2 ]4 y3 D! l+ U$ W0 r8 O3.原始式套接字(SOCKET_RAW)
4 P- j1 G- a8 S; z6 \0 a6 K9 [ 该接口允许对较低层次协议,如IP,ICMP直接访问。7 g9 }, o7 \0 d7 N
6 f: N3 z# _0 m5 {
二 基本套接字系统调有有如下一些:
9 X2 c2 B$ X4 M, L1 B$ K+ {2 v% O 创建套接字: socket()
( Z' N, t/ T: a0 l V3 K4 H8 F 绑定本机端口: bind()% o$ ]$ [/ k1 S' H
建立连接: connect(),accept()! G& ~1 p ~4 }: ~$ [
侦听端口: listen()" U' O0 v& K9 r7 l& v) |5 t
数据传输: send(), recv()1 C6 l( w+ n' |
输入/输出多路复用: select()' D ~3 f, A" o# o; ]1 X) Q+ B
关闭套接只: closesocket() g& m& I3 P) L- ^9 ]
8 h7 {) [' u1 ^# R! Y8 a& |' x三 数据类型: g, J& l9 Z# U# |$ U7 S k0 F8 Z; l
struct sockaddr+ @2 p9 N! v& B; I- b& @- O
{
: Q' l& E1 k; f unsigned short sa_family; //地址族, 一般为AF_INET- C. B j+ R) B4 N+ p( @
char sa_data[14]; //14字节的协议地址
1 U, f; ?( Q3 W. R6 d8 {/ y }
" e) S0 V8 ^" X' M2 v/ x" A; i& l8 A- ^1 \$ J& y
struct sockaddr_in
A( I; F7 x0 t {8 t) z' N2 h$ Q2 y% V% [
short int sin_family; //地址族
) ^' k1 x! \' r% K0 v5 [2 D& U unsigned short int sin_port; //端口号- a8 l4 Z& I3 t& ?: B( S
struct in_addr in_addr; //ip地址
/ ~7 K1 k" h* |1 g. M! x7 N2 _ unsigned char sin_zero[8]; //填充2 i) f( [+ P) l9 x4 Y
}
6 Y6 r* u# D# r) B/ Z- `7 ]5 C9 P! h1 Z/ A
四 常用函数1 l0 v) V1 Q5 R8 i( C' S
1 socket()
" v& A$ H0 y: c! D+ T 头文件: $ k5 {' B2 a( r1 i
#include <sys/types.h>
) i$ \2 E B8 E* f) P9 {; d; W #include <sys/socket.h>: n# x/ R8 B6 s" U7 ?9 V+ \
函数原型: v9 B2 P! Z+ E2 m! w. z. P0 _1 k
int socket(int domain, int type, int protocol)- b6 |4 z( T: D3 G/ l; t3 r8 D3 y
domain: 协议类型,一般为AF_INET
U1 a1 M: O1 C7 f1 n type: socket类型5 f: L" p" o3 u N. L1 w5 w1 f! H
protocol:用来指定socket所使用的传输协议编号,通常设为0即可" t6 E' X1 _( ]& r. b) D
9 o1 m6 a! {& J5 S+ ^0 Y. ~
2 bind()7 V1 o* Y1 l% T1 h
头文件:# f w" `3 O% u
#include <sys/types.h>& m4 [; X. {( R# @9 a
#include <sys/socket.h>, w0 ~4 Q$ h- O5 p
函数原型:# M$ r" ]0 @& j; T
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
1 _! f1 | f/ w0 {) U# ~ sockfd: socket描述符
/ {' U& Z$ t* i( ~+ n& @ my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针. f' f2 }( H" J u: v2 I) m
addrlen:常被设为sizeof(struct sockaddr)
7 R' ], n0 ?3 \! n3 M
! S1 C9 I5 |0 A' _8 k8 V 3 connect()
$ F6 Q- K- Z; L: x7 h, v- G0 X! C, M 头文件:( C4 n! ~$ e% B
#include <sys/types.h>
" Z( o& L1 }0 m9 D! X' u5 r+ ]7 E+ U #include <sys/socket.h>6 d+ T0 Z" B ~. M3 E8 k
函数原型:
0 F0 }; o* m( i$ M4 a- U int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)! w6 O- @3 S3 v# q/ ~ Q# \& B( n- M
sockfd: 目的服务器的socket描述符/ Q7 ?! q$ W9 Z& v9 H
serv_addr:包含目的机器ip地址和端口号的指针
/ v% y1 \/ h4 }& y9 P addrlen:sizeof(struct sockaddr)7 g3 m6 z8 E$ r, ~7 u
, d" ^) C+ S/ t( t9 _8 q7 o5 @4 x 4 listen()# B! a! D c1 R
头文件:, S% C# H% V9 W$ G; b! K
#include <sys/socket.h>, r% I$ L E" ~0 |/ _% v- ?
函数原型:& @ w2 r8 ^/ r8 B# v W: ]
int listen(int sockfd, int backlog);
% r# ^6 m. t: D. s9 [9 w" l sockfd:socket()系统调用返回的socket描述符6 A' D( \8 ?4 {/ Z, J7 n
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。$ d& [) q7 H& B5 {2 i
$ l1 e6 M6 p2 N+ M 5 accept()
4 W0 n9 ], W5 q6 m4 X( v; l5 f6 W 头文件:
, ]2 @/ P( z8 @ #include <sys/types.h>
0 }, }$ ]- ^* n$ g+ o, B+ Z #inlcude <sys/socket.h>
+ h/ L. j( A1 m2 Q" `: e G 函数原型:
* I9 ~& V% _: G, N int accept(int sockfd, void *addr, int addrlen)5 F& W- e4 r7 A# Y
sockfd:是被监听的socket描述符
' X* p: e/ N: e- H1 E p addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
, V$ ]. M, N5 y! j" R8 u; A+ ` addrlen:sizeof(struct sockaddr_in)* B# [( Q& V- C, Z& U. ^( }
+ h) l. Q( @% x9 x 6 send()
- ^" T/ B" Y0 m" [9 S$ c1 ] 头文件:9 O5 c. d! T* S# C2 q
#include <sys/socket.h>
4 Q$ C0 _* l0 L, `3 v 函数原型:
5 w. D7 `/ x2 C2 V6 E int send(int sockfd, const void *msg, int len, int flags);
* F1 K1 E }& O/ O( @, x sockfd:用来传输数据的socket描述符
. }( J! n% [! n, v0 g; }# ^8 r/ o msg:要发送数据的指针
( N3 j% h: S: P2 t3 a. n flags: 0+ O# Q. T% N; `7 o
, d& ]) W$ s3 c- [ 7 recv()4 W |' D3 Z6 W# s, e& z. H" H
头文件:
% S" P y& Y6 s! h V" M #include <sys/types.h>
H7 Z; M+ x: v- } #include <sys/socket.h>& T) S' s; J/ i$ U5 }, ]* d3 W* A
函数原型:
* _) D0 Q' i# R8 O9 v( d int recv(int sockfd, void *buf, int len, unsigned int flags)' l' v: A2 @5 V: Z* ~
sockfd:接收数据的socket描述符
* |# y( C* d3 `$ D& e. u2 t buf:存放数据的缓冲区
: D5 H3 Q! e! K2 ~: d2 a len:缓冲的长度9 N0 i+ R- R& x2 @/ X
flags:04 T# K5 w' t7 T' f
& c: P8 O/ [5 e7 f: s 8 sendto()
6 j, k* _( N4 D0 }6 y 头文件:% s! t5 H+ C* [0 e% q
#include <sys/types.h>7 `# S' k g, w$ Y' X, ~. d
#include <sys/socket.h>) B; [' y! P4 i1 q1 ~7 Y; I( t
函数原型:9 T: t2 |+ W8 r, v/ L- ~3 D$ e
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);$ Z. M" I! \' q$ Y( x3 F. G1 V
" ?, c8 R1 O- r1 b% w" e5 `9 W 7 u; I. O4 |5 G* q
9 recvfrom()# W+ ~( m- t- C1 _/ E6 s' c' l8 _
头文件:
" i9 X: Z. V* x, ]! d8 |6 s" i #include <sys/types.h>4 F( S3 b& I2 t
#include <sys/socket.h>3 ?1 `; ^& S7 k8 V( r
函数原型:
7 d. V. m! P9 P; r' Q% M int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)* G+ X& t t: t. |2 ^+ k
: `/ A' I$ w$ y5 Y9 d5 P. G( i
7 b- u' ?; P7 @8 x! w/ O
10 read() write()
2 y4 ]; u. ]; y# s: P int read(int fd, char *buf, int len). `6 j% h- R( m7 j5 p: O8 o
int write(int fd, char *buf, int len): {7 ~4 W, k. h8 Y2 I
& h0 O) F' a, U6 g) K: h/ t 11 shutdown(); g+ o. Q0 I" r$ n ~
close(sockfd)$ e. w# A& E8 n0 ?7 y
int shutdown(int sockfd, int how)
" k/ [+ E, q5 Y4 _: ^" b: Y4 a/ s----------------------------------- [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 ]/ _) n) d2 N1 p! S$ J<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
% B: I2 i* b# d% ?% _* d<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
' L) N9 n* Y2 L<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等% `- ^0 n5 t0 U
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
" v9 z: s# D8 E6 r3 I<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
7 L6 r8 }+ E1 Q$ u<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件/ J8 g, y" e' ]$ P5 j- L4 j
2 F7 a- X9 R$ |2 v9 z% s[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
8 o- I& o3 u1 A* ~7 L% i#include <sys/types.h>
" K: E" ?( [5 @. Q8 o7 I/ J5 v% `1 W% ]7 i( Y: Q0 C
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
- Z* \5 ?& T' l# D- w) `! k#include <poll.h> //poll,pollfd
( c- U: y" g" h* E7 Z8 z9 H#include <arpa/inet.h> //inet_addr,inet_aton
t! ]4 X& w" V" A5 s6 Y#include <unistd.h> //read,write' ^# X: C3 E; O( {5 o
#include <netdb.h> //gethostbyname' n _1 _& h1 B
5 x0 m( P) e; X4 E4 `1 |
#include <error.h> //perror
1 V; p" d8 X0 r5 E8 J, r. }6 S#include <stdio.h>& d& a2 w ^' T/ h- y U
#include <errno.h> //errno. i8 n, M& ]) r
9 B/ U9 F( X8 G: m0 K+ e" n- Q9 y! S#include <string.h> // memset5 m* ?1 I, S% D
#include <string>7 w) H; m( j3 S
#include <iostream>
6 D8 [) e/ P# d. y% O, ^6 t. ?' |" @# M! H: V
|