|
[size=13.3333px]一 三种类型的套接字:
8 D. J R9 f: ?* D( Q6 U& H+ c1.流式套接字(SOCKET_STREAM)
1 a1 e+ C, f9 ] 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。# j: q' U+ z O5 `& F Y Z/ i, {2 Z
2.数据报式套接字(SOCKET_DGRAM)
. F ~. h5 N! r* R 提供无连接的数据传输服务,不保证可靠性。
! {$ E4 y' H8 V0 N3.原始式套接字(SOCKET_RAW)
* q' ~8 @/ b2 ~! H 该接口允许对较低层次协议,如IP,ICMP直接访问。
2 O; j' n( ~+ v4 N1 e6 M
0 c8 ~( r6 R, k4 J二 基本套接字系统调有有如下一些:
: x& W$ Z$ g# G* P9 a 创建套接字: socket()0 n/ m; C; p' s0 P* [! P3 ]( R
绑定本机端口: bind()# g3 Z. ^+ }/ V) e2 [
建立连接: connect(),accept()
' b1 e; s( b" u- c. k( C) L5 c 侦听端口: listen()) q3 U; I5 \+ C: N8 s
数据传输: send(), recv()
5 [6 b8 K& J- A! I: E 输入/输出多路复用: select()
6 K$ ]( h" i$ ^% C' E6 g* \ 关闭套接只: closesocket()! D% ~, V% i/ X; Z2 D: v2 |* R% V
) }, V" k) |* `+ q! n& `* @5 o6 v: k7 U
三 数据类型9 A3 z1 @: C$ G1 J& b) X- r
struct sockaddr
8 w# `" M) {1 g/ W( u) Z% s$ A {; x# G. r9 E9 g; Z5 x2 h) l
unsigned short sa_family; //地址族, 一般为AF_INET& Z) N# \9 ]5 F8 j6 N' I
char sa_data[14]; //14字节的协议地址8 T+ E/ E# _+ `- c7 q/ c/ x
}1 w) T, {3 g, l6 C L
4 _* G! M# u0 e5 O0 f
struct sockaddr_in
0 m# e5 |; y) c h% Q {
& x E* O6 G6 z2 b0 y% Y- r short int sin_family; //地址族* M% F( |5 ]. O2 x( e
unsigned short int sin_port; //端口号
" W" G& w V( W5 U0 R2 D struct in_addr in_addr; //ip地址
3 t1 L( y5 B. o% h6 f7 w unsigned char sin_zero[8]; //填充& ~* b, v( c/ n: y
}' E S w h' m
/ A2 r* [! X8 J) h1 l' N" e四 常用函数9 q; M6 }( a% d5 I1 c
1 socket()2 w0 x' i, m; G' h2 X4 n
头文件: 7 X' }* P) D7 G1 u) X5 I( u. r
#include <sys/types.h>! D! \" S0 y+ g3 }8 y( ]% c; _" I
#include <sys/socket.h>
6 I* W2 c6 { l5 _5 A6 O 函数原型:7 m* D: F: g1 ]! d
int socket(int domain, int type, int protocol)
7 r4 D; G5 X+ M( [# R S% | domain: 协议类型,一般为AF_INET
& W9 t/ `; o- N; U0 d* g! W8 _ type: socket类型
/ [% k0 Q& j( U! q& J) v* y5 c$ ` protocol:用来指定socket所使用的传输协议编号,通常设为0即可3 Q8 ]5 G1 o# _; p- I
9 f7 C) y3 D& Y" ]7 V2 l' `
2 bind()
5 D4 i" C: S. N5 ?. S3 D& p( j 头文件:% B7 C9 [$ l7 U2 W5 [& C* r2 w6 T
#include <sys/types.h> a6 k0 q p. | T4 F F
#include <sys/socket.h>
8 | A8 w W" Y/ H 函数原型:
% } v% H: M) z& {8 `% Y int bind(int sockfd, struct sockaddr *my_addr, int addrlen)4 O- ]! z- n% e3 }* T
sockfd: socket描述符: p; \6 G/ A% K' \
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针/ N7 I' b; T" Y7 }+ b4 G
addrlen:常被设为sizeof(struct sockaddr)
! Q! W* d5 u7 n3 J. p5 j+ \3 t) p( z% M1 _
3 connect()
9 i- \4 }7 p/ k! o4 i' N3 ~! m 头文件:; }# F* ^, c6 E% {
#include <sys/types.h>
' F/ E( E# N: o. ]! z$ t9 S #include <sys/socket.h>6 _; T& z* b* g& ^8 {7 T3 W) I
函数原型: L7 g& g+ ^# S- U5 T3 r( Q/ w
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
- F: M3 ?3 e$ W7 W* K$ z! J1 h sockfd: 目的服务器的socket描述符
2 P: `: f2 d( I# p/ F L serv_addr:包含目的机器ip地址和端口号的指针" Y" f8 @* J k8 `3 B5 G+ a7 k
addrlen:sizeof(struct sockaddr)
/ A% g! A# w" h5 |- @3 D4 S M( J7 y* {) Q# e. v
4 listen()
+ h$ V6 E) j& e- m6 f+ c; |5 [ 头文件:
! J8 W2 p& R" `: H( s9 @0 { #include <sys/socket.h>3 G& R. v- N/ `4 e. G
函数原型:
+ a' O5 v9 b) l* I$ g int listen(int sockfd, int backlog);
" v ^: x2 D2 G sockfd:socket()系统调用返回的socket描述符
' b, {3 }: k2 R backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。
. S/ a) H: F) V3 d" U9 I8 D; ~9 ~$ `: W, K
5 accept()# S$ N: \, ]& X2 F" A' a
头文件: `1 ~& o: ~5 c7 e6 ^/ b7 l
#include <sys/types.h>' v8 v$ G5 y' f4 z ~
#inlcude <sys/socket.h>
, k: P. Y" `0 P4 b: v: u 函数原型:! N( x7 t2 P; b$ q2 _
int accept(int sockfd, void *addr, int addrlen)
* s% i% m; [ O7 F; w sockfd:是被监听的socket描述符. z0 w7 l" S7 s+ \" u0 a
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
" k$ V* |/ Y) |/ f: _% S addrlen:sizeof(struct sockaddr_in)
0 E* p5 ?% f: R
5 c( R# C) d- b8 h 6 send()$ D( ~( d- J+ F/ ^
头文件:
$ m& `9 I) G$ t: Z6 U9 } #include <sys/socket.h>& N# J8 {4 _% }' u W
函数原型:' X. @2 D7 k! x& c9 n# q
int send(int sockfd, const void *msg, int len, int flags);; h2 q2 U/ {! V4 T2 t$ n
sockfd:用来传输数据的socket描述符
, Z1 v1 i W# @2 A7 [6 X' a msg:要发送数据的指针 & ?) C9 V# _) ^! C
flags: 0
# n5 ^% X4 d: {( ~8 U 1 ~7 U6 m6 u' a4 w; U+ ^
7 recv()8 o+ c4 e* L' D9 J r T
头文件:' k/ k: @1 V# S4 m
#include <sys/types.h>
a3 t& N: h2 N #include <sys/socket.h>9 G. ~/ g3 {3 }$ c8 b
函数原型:, W5 \5 H+ o9 {" z1 Q& C% N
int recv(int sockfd, void *buf, int len, unsigned int flags)
# M* m# i( B }7 i sockfd:接收数据的socket描述符7 I! U( b$ S& A& Q$ B% B2 B- u
buf:存放数据的缓冲区
1 V* V ]) R. ?3 a! X( Q len:缓冲的长度9 h3 M ^4 K2 c* ?" d7 @) \! x
flags:0
( h$ [4 D, s# p* z: j! S: {9 S% w. [, K) a4 L; H/ X
8 sendto()
& `( `. P5 O' A( S' v 头文件:4 M y% D% U, Q
#include <sys/types.h>3 n7 ]: D* B8 P, p5 ~# D, l2 F
#include <sys/socket.h>7 N% M3 W. I7 A, U) Q5 }
函数原型:
- z- o5 q. R/ @# w4 O int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);# v, R( w1 @, t2 R
3 `/ v+ l$ @3 T# Q" n
# d5 Z( K* F4 G8 ?2 Q 9 recvfrom(). L' Y/ ^7 b7 Z# L6 J# d- ^
头文件:. P' q6 ~) V; Y2 R+ y5 B
#include <sys/types.h>
- k1 M+ h9 B3 M7 g+ X #include <sys/socket.h>- \7 v2 h7 x6 j6 z( L9 z
函数原型:( g! |2 A$ s& w9 T+ J% V
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)# w; j) I9 M: Y5 d
5 z! Y8 I6 l& V! M! Z4 D
1 o- t6 c& A4 a8 m9 J& H2 C 10 read() write()9 h2 r1 \. A; r! T
int read(int fd, char *buf, int len)
2 _( I; i, h$ ^: e int write(int fd, char *buf, int len)+ G" p8 \! l, h5 D5 w% a( t
: _2 L# G! Q; @/ s( k
11 shutdown(). \4 [' O {4 E5 S
close(sockfd)
( e5 k) P* F# k" G" }1 x int shutdown(int sockfd, int how)
; ]1 y. G" y+ \5 m: ~----------------------------------- [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等) ^) B2 ?! }# k
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
% ]. Q8 u/ D9 ^% @6 `<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl(). R* [" I# j6 e5 S7 z- d5 t5 C
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等3 @' y7 S+ `8 v7 m2 A
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等' z9 m% Q C" s; s% X+ Y8 b
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等( U4 m$ c: ^( e. s# y
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件& X# ~' G/ K) c+ R! N( D1 V s
$ w' n* |2 A m/ \[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等, q1 ?, `- [# g
#include <sys/types.h> % r; t6 c. K; ^6 F3 I6 Z
0 j: x, W/ M+ k: |
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
# ~6 y4 a U+ s; h3 ]8 [#include <poll.h> //poll,pollfd3 {; Y# W# p j' n* p1 t P2 {% h
#include <arpa/inet.h> //inet_addr,inet_aton
4 Z6 l# F" S* o% f4 r' A" u* h#include <unistd.h> //read,write
6 y9 R0 n5 _' i/ b. y2 g; ]#include <netdb.h> //gethostbyname
9 i* N6 T0 b$ T% A
; }% N. D* S; C; |, j$ w2 }#include <error.h> //perror
) ^/ }# y& R, m1 c& o" V; i#include <stdio.h>2 P4 m B. r) y
#include <errno.h> //errno3 y! ?8 W y" J/ ~: f4 Q+ d
9 T# j x, n+ |) u% z7 k4 N. d6 A9 o#include <string.h> // memset) j4 K& E$ O2 `" y% R' T
#include <string>( W: A; T6 e* w% R
#include <iostream>) ^9 q7 x; A$ S' P
7 M0 s' E0 x+ [) z1 P# I |