[size=13.3333px]一 三种类型的套接字:
5 R# ?. q$ b) r; d8 p. m; O5 P1.流式套接字(SOCKET_STREAM)
- R0 T5 T, N/ ?6 U3 X! ] 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。 O9 E/ d# \$ ?& l. ^
2.数据报式套接字(SOCKET_DGRAM)
" {. O6 K/ L* M! e! [ 提供无连接的数据传输服务,不保证可靠性。
8 ^& O3 Y& O7 U5 `, P3.原始式套接字(SOCKET_RAW)
* w4 G( s& n2 c 该接口允许对较低层次协议,如IP,ICMP直接访问。
* V# y+ u" p8 B% h. a! m2 y2 ^ H& S6 L: A- l$ s+ a0 ]! t; h2 J
二 基本套接字系统调有有如下一些:
* x E6 D0 n, `" g+ {, E. k+ A 创建套接字: socket()7 k; O1 t+ ^1 ~8 a/ m" R
绑定本机端口: bind()
8 J3 ^5 [& u3 d1 J/ b; p! @ 建立连接: connect(),accept()
6 C+ T, W e( L! o8 d 侦听端口: listen()
6 r5 [7 K4 ?5 \; ?' J+ Y 数据传输: send(), recv()
( @8 U- ~; |! a$ q 输入/输出多路复用: select()
' y. `, u; P# {. x 关闭套接只: closesocket()
5 {8 ~* ^+ V2 r/ S5 ?: d * X# N: H/ d. i0 G! M
三 数据类型$ v H3 x5 _# V5 ~
struct sockaddr
( ?( b/ G/ k8 L1 A1 B2 | {/ {( m6 Y2 x4 ]! [4 Z F: X8 V3 t
unsigned short sa_family; //地址族, 一般为AF_INET
1 F8 v( ], m9 H) \+ v5 ^" d char sa_data[14]; //14字节的协议地址
- g/ a7 w a' ]- I8 f }
b J$ E8 L1 U& [0 i
# t" S' h5 V' C" ?# E struct sockaddr_in
. ]' D+ r- y6 L7 Q8 W {
6 f# E8 i. G5 O9 ]) J! p: i3 @ short int sin_family; //地址族. T4 v# ~8 @0 H7 C3 n
unsigned short int sin_port; //端口号
. x( D6 d8 {5 K V; y q( `- @- o! x" f struct in_addr in_addr; //ip地址* M( x3 t! ~& S5 F8 T
unsigned char sin_zero[8]; //填充
7 R# R; o" X5 o+ u* B }0 l( J: o. K: u) Z7 K1 }, r
3 W1 i, ]& @& y) o% u, {四 常用函数
- y& A( e' x! C9 \# w) Z- A: R 1 socket()
7 O6 q9 [9 e+ i6 K- f 头文件:
' G, U P6 f" i: b( O+ D #include <sys/types.h>
* S( t& @) A' B7 V" j& a2 \ #include <sys/socket.h>
1 i4 s% S8 b1 O/ ]. Z0 K 函数原型:" a) w- k8 x$ S ~- p
int socket(int domain, int type, int protocol)) J" U: l5 ?5 d
domain: 协议类型,一般为AF_INET0 f, R1 r& a- Q* [& q% h( Z4 h& \! r
type: socket类型1 F. m, o7 V7 J% ]6 i5 _- Q0 u
protocol:用来指定socket所使用的传输协议编号,通常设为0即可' i: q2 E, u7 |8 L; A
1 W1 o5 Q- t" I1 `2 A6 O
2 bind()7 k7 }+ R4 R/ |" Y# {) h% t
头文件:5 B$ ~0 l' O2 Z0 v2 X4 V- M6 t
#include <sys/types.h>' p. ^0 b1 x: x5 q
#include <sys/socket.h>! b% P& N3 `# u% r e/ q$ s$ F6 @
函数原型:. e* u2 | ] q
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)6 N! }3 @" L7 v& ?/ i Y3 d% e' H
sockfd: socket描述符* [$ c$ g" q- z7 w6 M0 p+ E
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
- j7 S f6 D$ e9 s" { addrlen:常被设为sizeof(struct sockaddr)
6 A% m! p9 g. s9 z6 e7 a% Y
) X# I8 @; g' ?( t. i5 \ 3 connect() B9 Z7 K s- I8 w7 G8 E5 E0 ?
头文件:
4 o& T; ]1 a" M7 }% d #include <sys/types.h> ( H! j/ ^$ i# p4 C
#include <sys/socket.h>& e+ K/ n6 |! p$ H8 ^; x( R! p
函数原型:# P, |4 B( _, \, H7 s6 Y
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)7 O) F$ ]) Y8 X2 _
sockfd: 目的服务器的socket描述符
% P7 |- H9 p0 M5 `5 I, Z' r' j serv_addr:包含目的机器ip地址和端口号的指针- {* A L0 K% @: y o
addrlen:sizeof(struct sockaddr)" f9 G6 O5 R7 D9 ^2 b% x
, s, l" w/ G4 Z& Z/ k; M 4 listen() U& N( e! u# [
头文件:" B# w) n5 J' z* O& m! e2 ?
#include <sys/socket.h>8 v5 l* L4 A+ u) h* h( H9 ~
函数原型:! x1 ~+ e$ a2 \: [/ {
int listen(int sockfd, int backlog);1 H" [8 ~% ]% a
sockfd:socket()系统调用返回的socket描述符# r# m# B. t, ?& Q7 S
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。! P9 R3 X H0 a
: w5 q. N2 P8 K, G% b
5 accept()
; H, l( @; H; d6 K7 R- I& ~ 头文件:
1 I, y+ i# M- A+ Y" d #include <sys/types.h>
_: h2 S& V3 |9 i9 Q0 _( F2 [( t #inlcude <sys/socket.h>/ [: x2 h& B/ M* r, B. J3 D
函数原型:2 ?* T& N2 D" X
int accept(int sockfd, void *addr, int addrlen)/ M6 G& S" w ]% | [) A
sockfd:是被监听的socket描述符* X( @3 X' E, B- U! @& f# s) {- H$ u
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息: a. @3 w8 E) P
addrlen:sizeof(struct sockaddr_in)! c X$ h+ q' S8 Q$ x x
( ]7 r, `3 z* {7 c3 T* J
6 send()) ~; p' C+ f) C" t2 y
头文件:% p" Z. s: j1 U% |- T! o
#include <sys/socket.h>. } B [; @3 q" B3 n u
函数原型:
/ }7 | {/ W9 w* c int send(int sockfd, const void *msg, int len, int flags);
7 E+ o8 c+ A/ s0 w, Z; T2 q" P$ A sockfd:用来传输数据的socket描述符. w2 D4 q8 p9 W( V' B
msg:要发送数据的指针 / n, e/ @( \! @9 L3 y I
flags: 0
% _* o- Y3 g* p
# p( z' ]. K) X2 l, e! ~: R4 H 7 recv()" F+ J# R( A" w$ p( T2 V$ ?2 R
头文件:3 j+ l0 ^' H2 x5 s
#include <sys/types.h>
) a( g$ V7 |2 p" w #include <sys/socket.h>
8 x, B& M1 D4 B7 Y( O 函数原型:
5 t2 l2 `2 l" `- F! N0 g7 d3 Y2 j int recv(int sockfd, void *buf, int len, unsigned int flags)- @' w& _ ~1 }0 k1 w! i
sockfd:接收数据的socket描述符
0 p/ @/ Y% S& q' p buf:存放数据的缓冲区
: S4 ]: |! ?" B E- a len:缓冲的长度
" H$ N* J% f9 ^$ c4 O flags:0+ K+ x! a7 f) V+ L- T+ J
$ Z, p7 U* b: s5 _3 D5 K2 [ 8 sendto()
4 B7 I N/ ~9 a8 {( N 头文件:
; s8 F7 p0 h/ L" y% [ #include <sys/types.h>
, h/ @/ K# X) L4 W6 N #include <sys/socket.h>
( [+ x, a4 |+ \# w5 r 函数原型:6 _# _# K( J+ ^. y" a7 G
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);& _1 W6 ^8 `8 O S
4 E& A% {+ R: n8 ^& T1 Z: p; B& m& \ 3 j! T+ X3 N" R' }
9 recvfrom()
, Y1 h* v# j: x, r `2 @' @) ? 头文件:
, ?5 H9 L1 V/ P+ v #include <sys/types.h>
2 N; d P# }7 v' u9 G4 D #include <sys/socket.h>
; W+ k0 w: n# t$ v 函数原型:
# O1 y5 |/ v1 W7 J3 ^ int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)( t4 a r1 Q" A! I" h3 q& i' N
/ j# v! c- v( ]* i/ ]. \
4 N$ c, q* s6 d6 `( J 10 read() write()
. K% c9 C6 R- }: |, N) M# e int read(int fd, char *buf, int len)5 y5 |2 Y- L$ Q5 C- @* F" r
int write(int fd, char *buf, int len)- H8 V2 h. r i, G* C5 {
' g6 L; H2 g. s, o- T
11 shutdown()+ g- Z: t+ `+ Z
close(sockfd)
& p5 s# a7 Z$ I, {* z5 ~ int shutdown(int sockfd, int how)
, d8 }$ O$ G7 d6 L/ z9 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等)
7 G+ v% l/ o, y# }* x<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
/ M) b, N# N' ?% S+ J, f<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
. L1 a) W. s7 r$ V0 h( c<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
* Z) l, v& x" H! n( V; x<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
" s w, ]) X' L<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等/ Z$ c. R; Y( w, R' S* c8 v+ A
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件. `" Q5 C4 `4 s' v: y# i
& a9 K' R6 G+ U
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
7 k. X+ B3 C4 b$ p+ m#include <sys/types.h> 3 ^- b+ j" i8 z2 M
! i7 A" \4 l# b2 U5 u
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
- F& v k* T- I! D1 L#include <poll.h> //poll,pollfd
7 @! C, z' `! s& B5 f! K#include <arpa/inet.h> //inet_addr,inet_aton
8 P# A, r+ ]: g0 E6 I, b#include <unistd.h> //read,write! @* |1 \7 U% K' U5 L+ B O
#include <netdb.h> //gethostbyname
2 _3 _. j5 F/ q8 `' k7 s) o8 X; v# @$ t' s" g, D+ F
#include <error.h> //perror/ j: _& F: b5 }; L9 H0 B/ i' K
#include <stdio.h>2 g* O# ?8 n W, M- }8 F* h6 l
#include <errno.h> //errno
6 k( c/ V6 J" t) }
* f( ~ j/ K9 i9 s( S#include <string.h> // memset
4 w7 F7 x% ^4 u. j# Y. [#include <string>
0 l$ }& R" F( P& y6 E+ `#include <iostream>
9 {" ?2 k: Q1 E6 e" d: G" ~1 N0 \5 F3 Y+ J6 U
|