|
[size=13.3333px]一 三种类型的套接字:. j) b; r9 n+ ^. R
1.流式套接字(SOCKET_STREAM)9 G j7 D; I4 U# `5 z: J
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。/ m8 v: G6 v% k1 D- U* l
2.数据报式套接字(SOCKET_DGRAM): Z) w6 g7 G5 y/ ?5 ]7 v& W5 F4 E: ~
提供无连接的数据传输服务,不保证可靠性。
, O+ {* p4 p A* N* K3.原始式套接字(SOCKET_RAW)
' j3 W- [: K5 k 该接口允许对较低层次协议,如IP,ICMP直接访问。
# d O" U6 I* I4 {) O3 a5 I. n, w) k1 O
二 基本套接字系统调有有如下一些:
2 x: L8 _/ |4 R+ B" C4 t! d 创建套接字: socket()
. e' h8 M F* g1 g5 q4 q 绑定本机端口: bind()
6 |- o8 n6 a- g1 c( G% f 建立连接: connect(),accept()
S& }. C2 A$ _; \5 Y( C- j 侦听端口: listen()& |; x! S" b- Y+ G W# e
数据传输: send(), recv()
# C: V: X3 S1 r 输入/输出多路复用: select()) v: a" |/ @* A4 s
关闭套接只: closesocket()- K. Z# Q, M m4 m+ j. l" ^
/ O# s9 z, c% F1 o
三 数据类型- |$ L3 r9 ]; Z: X( d4 b
struct sockaddr
: `+ B% ` ~6 T% a: R {
9 x, O% Q" x, d8 B unsigned short sa_family; //地址族, 一般为AF_INET7 H/ X8 c/ k( b) ~5 U
char sa_data[14]; //14字节的协议地址
! U% ^$ e. q' j* S' [3 Y2 _ }
7 Q! d: n _% ?9 f7 m
% |0 D2 J$ w K% M& a5 | struct sockaddr_in2 m- d4 T. `; c+ W! ~. k3 }
{& ^) B0 v) X2 u6 v; b; L
short int sin_family; //地址族: e1 h% U* Q: {( v& X3 g
unsigned short int sin_port; //端口号
* H0 ]$ t) W6 ]; N, D struct in_addr in_addr; //ip地址$ B. h! f# j: G) K3 h
unsigned char sin_zero[8]; //填充+ F# l* K8 V3 l9 \# y" p
}2 J" W6 n) {" h8 P* p6 y2 d: H
* m8 c& u% |2 S% `; M8 b, i四 常用函数# d' D- f; G4 [, i# L. N6 r* u
1 socket()$ Z _6 l( e: j" F* e
头文件:
( E/ B' K. c7 { #include <sys/types.h>
0 _8 n+ ^# S% M; H* r: m/ Y #include <sys/socket.h>
3 \+ A& }- o- ?: ~& X( y) G 函数原型:
" z2 \0 ]* ~9 [* f int socket(int domain, int type, int protocol)* g, G K8 |. Y: m
domain: 协议类型,一般为AF_INET
) ^+ M6 p; s2 U5 c, M$ [ type: socket类型, o+ C1 p7 R; J* m' f
protocol:用来指定socket所使用的传输协议编号,通常设为0即可
, K9 o& b0 S X6 l- I% H& Y2 `0 k. X- i! A
2 bind()
8 Y: i2 t7 b; X% C2 q: b 头文件:8 l8 b/ ?9 a7 |, y8 N* i: g% J0 D4 _
#include <sys/types.h>
U+ V7 C1 V9 c #include <sys/socket.h>% I3 _+ N" p6 {3 ~
函数原型:5 q" E+ ?/ f+ l: ?& [6 v& O
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
6 b% q2 ^2 m* H* ~3 r sockfd: socket描述符# M, |; j4 u" u
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
2 ?( f2 A7 g* G" C( x J, } addrlen:常被设为sizeof(struct sockaddr)( i& i" E) \0 L* I$ i
1 |& Q" m7 `' i0 h! F 3 connect()$ b% ~ p [+ @ g4 Z8 f
头文件:; p9 I/ o2 K3 N m! R
#include <sys/types.h>
4 L4 ^4 y: i" v0 | #include <sys/socket.h>& j. q. ?; O8 d/ C* Q
函数原型:) ]* M, s/ x4 ~5 |
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
3 G. i7 p% i' J5 L! r sockfd: 目的服务器的socket描述符
- X) o( m! u, h' R" J& `: C( t% o serv_addr:包含目的机器ip地址和端口号的指针% s# l. h! `8 K: s6 R" c
addrlen:sizeof(struct sockaddr)
: E% p4 ]2 m2 `6 T5 }6 h, n# b i2 Y! M5 ~, x3 `4 f9 i' s
4 listen(); L6 p) Q+ X8 S4 B2 H0 S
头文件:
; v6 n" F5 V0 ? #include <sys/socket.h>9 `" Y. x& P, ~( h& \
函数原型:+ o* x4 u" U3 @8 q
int listen(int sockfd, int backlog);
. |3 [, y+ j: A8 M- { sockfd:socket()系统调用返回的socket描述符- n2 V$ @% j! k) |' p
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。
0 W4 a' Q% {8 k7 k
( x7 N4 d# ^) n: J/ S9 W 5 accept()
' d( B8 E% w4 `6 o# ? 头文件:
6 j0 l4 S" g! f6 H+ _( x #include <sys/types.h>
% n& t7 _- ^' R3 V$ r #inlcude <sys/socket.h>
- J4 B) \: t' V9 o" L3 z/ L 函数原型:
" p3 }9 T" N5 u int accept(int sockfd, void *addr, int addrlen)) M# d: R- q* B" Q5 P
sockfd:是被监听的socket描述符
- e& J) J! H6 N+ V addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
# n: F u% o* z b. R8 F addrlen:sizeof(struct sockaddr_in)9 G# @* J$ ~0 `) ^
/ w7 X# |1 c% o" j* d! S7 f) M* O 6 send()
* }; M3 M4 J" F: O6 [ x 头文件:( Z7 C7 W! k. V0 H: G0 @2 O- N" d( k
#include <sys/socket.h>
$ S, b! P7 ?$ j' ?9 H 函数原型:8 r( g2 E; U+ D% X$ A/ e) b1 K
int send(int sockfd, const void *msg, int len, int flags);
9 {' I/ B2 P' K2 h \/ v2 p sockfd:用来传输数据的socket描述符
. x; V% G; H0 I- P# Z msg:要发送数据的指针
9 p6 C/ R) C7 i- O; R/ ]* a3 {6 q( a flags: 0+ z+ R- O' b3 [' Z! r7 V, t! @8 R
. w( Y7 O& }: }9 t p1 W 7 recv()% X- P, X. h x6 O i1 K
头文件:# U, s3 K6 r+ y+ T& @) W. B
#include <sys/types.h>
5 h; o- ^/ C- ]3 } ]5 a #include <sys/socket.h>
" z" w6 U( g/ \% L0 ?6 W 函数原型:/ t( r8 k$ w6 K7 Y o* s( ~
int recv(int sockfd, void *buf, int len, unsigned int flags)7 o/ S R+ V/ ]8 T* O
sockfd:接收数据的socket描述符
* h$ M) D4 f5 K$ D buf:存放数据的缓冲区4 r# Y! I6 @9 M6 A
len:缓冲的长度
6 m4 ?! j' L+ n7 g' Y flags:0# L9 W. f `. _
" v7 ^( Z2 A9 e5 C0 y; B
8 sendto()
* S7 W2 y* Q3 ^0 n 头文件:& E3 z% P& A' i7 w. b. Y. H6 P
#include <sys/types.h>! ]- I% c3 I7 l" s6 D
#include <sys/socket.h>
5 D, c1 _) o6 o# o, H9 C2 m 函数原型:
: C R* g, C8 N w+ M# v/ _) t7 P int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
; ^2 D. f9 k& N C6 k
" d! P, T# H6 U' m ; p& w) m6 z% e0 f1 i ]) W: Z
9 recvfrom()
; u& N/ o8 S7 @) }* [/ \0 r- J 头文件:
( s% r* E+ w. n6 u% \% f+ \ #include <sys/types.h>: d2 x% p' t4 _+ s5 l
#include <sys/socket.h>
4 Q9 W5 f: A( N' @/ a4 Y1 ^ 函数原型:) p0 A5 I9 }6 l6 ]2 q h
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)+ s. p7 Q0 I( v/ M6 n' I
& D" T' k) g% A# t h1 k( S" ?
9 Y! W! X1 f; h2 F: R. X
10 read() write()$ t& P7 ^ A& ]1 k# l( a8 I
int read(int fd, char *buf, int len)
" n4 L2 `2 ]% [1 _( B int write(int fd, char *buf, int len)
4 s" ~! e- T$ A 8 a! ?. V$ L6 E! N
11 shutdown()
" _; A' \1 A6 Q& A* Q close(sockfd)
$ ^/ }0 r3 l& k( ~7 H, J0 _ int shutdown(int sockfd, int how)
! @: \5 o% r9 g% t! ~- V----------------------------------- [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等) ; Y a; e: k& w" ^5 v
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
9 {! B& E/ z9 B0 ~<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
* A9 g' S" _$ Q* K<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等1 T+ S P+ v/ i& D% f- p2 G
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
: W* i' v3 c. \9 X6 X$ n<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
0 C5 q; W: J# z& [- K1 Q+ W<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件( l( C: A& ?: s0 D4 `8 I5 Z# w
+ u' g" a* @# w" a
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
* F* V0 Z# @' J#include <sys/types.h> # I0 w5 C- c, E
$ b* F, R6 n8 ]5 v! \
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
% t. E3 u; H, Z' ^* ^0 f#include <poll.h> //poll,pollfd7 q0 K/ _; E/ Y+ @1 j
#include <arpa/inet.h> //inet_addr,inet_aton; _1 x3 Q- o6 W9 X. I; \( G
#include <unistd.h> //read,write: n1 B, w% K* E% i+ O1 ` Z
#include <netdb.h> //gethostbyname
. P* }" r9 x8 ]
' Q4 m' P- k$ j: y9 p#include <error.h> //perror: u; x; W; G# {9 \4 S
#include <stdio.h>
/ a8 a% ]3 j& k! _: b" F( z#include <errno.h> //errno, W; ^! w! r& r5 |3 M9 }1 B* p& W
, ~. u% s c! @1 n0 p, g( `
#include <string.h> // memset
9 Q% ?' j& h) V4 H' h+ f7 B#include <string>
7 P4 C8 q- ?6 S, o+ ]) {' @#include <iostream>
. Y2 ]/ i6 H9 R( h
6 M2 s+ b6 C: c) h8 ? x6 y. e2 ?) b |