|
[size=13.3333px]一 三种类型的套接字:; F$ i$ x* X0 W% _
1.流式套接字(SOCKET_STREAM)
$ D. X% c( L; Y# a/ ]. H2 e 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
8 \! l0 Y4 o2 W, i$ L2.数据报式套接字(SOCKET_DGRAM)! [' i6 A# `1 z- v2 y/ o6 ?, O
提供无连接的数据传输服务,不保证可靠性。 s+ h6 s7 I) b5 L6 g7 \9 }
3.原始式套接字(SOCKET_RAW); l4 h6 \+ p% N8 [9 K1 b
该接口允许对较低层次协议,如IP,ICMP直接访问。
6 [+ R) L/ }3 e. }4 h! S; O( n' S7 `- r2 F! ]8 U7 j2 c
二 基本套接字系统调有有如下一些:
3 \9 x! v, F+ {; V; g' P; T 创建套接字: socket()9 {' A( L9 n2 g) N
绑定本机端口: bind()
# X4 q4 K+ w0 Q* D0 f7 A 建立连接: connect(),accept()$ P5 z$ p( F q& q1 W
侦听端口: listen()# o, v/ j+ ]2 r/ S9 C
数据传输: send(), recv()# k4 K; H4 g# M4 l3 u- W
输入/输出多路复用: select()
1 H" v4 ?& o$ b* D+ u c 关闭套接只: closesocket()$ N3 p" P! W/ p7 Q) q
# {" t+ }& u, c
三 数据类型* c3 l, p9 M' f8 _' F- w
struct sockaddr. z, d- g! _, j- V( _$ e
{
5 Z7 K) q+ L8 x3 p7 x+ L8 M' i unsigned short sa_family; //地址族, 一般为AF_INET5 ^4 l5 m2 {" w" F
char sa_data[14]; //14字节的协议地址7 j; C. E' O# x7 T# p1 t9 I) k& {
}/ ^+ X, A" n& _/ ~4 V! X
/ u. T* W. O* j* b3 s( X struct sockaddr_in
) k7 b" T; P# u8 ? {% k* ?$ p* j' e6 i( X( f
short int sin_family; //地址族+ n8 {2 U' c. @5 _
unsigned short int sin_port; //端口号, {& Q& [: d ~% K! R
struct in_addr in_addr; //ip地址
l8 T! a$ E0 Y unsigned char sin_zero[8]; //填充
+ w8 N; f3 i! G6 l) L }4 ^3 o9 X4 s, k' B" m
0 \5 c* N# O5 B3 l) ]四 常用函数
; n/ l9 y' B& @8 _6 P; t) A+ a5 m: F 1 socket()2 H6 u! j$ S9 m& N
头文件: % k0 b" B) t3 r8 Z$ f3 A/ M7 q7 ?
#include <sys/types.h>
) F, ?' {) o- T2 X* @ #include <sys/socket.h>$ U4 c8 {1 _- r4 O
函数原型:
7 G0 |+ B# J3 u; e int socket(int domain, int type, int protocol). W0 X* b* c/ M Y+ W
domain: 协议类型,一般为AF_INET* n) h) e: V7 K+ j( n
type: socket类型, w: S1 ]! j5 v3 o. D4 P1 ~: d
protocol:用来指定socket所使用的传输协议编号,通常设为0即可; {7 `( k: w& j$ b/ ~; Z
- S- F+ Y1 j3 u1 C) s* k4 v6 E
2 bind()
( H& e- }, e1 z; \ 头文件:+ r$ B/ @) k2 D/ D: F0 H6 f
#include <sys/types.h>
% Y. o |/ H' ^9 B3 P4 Q" D #include <sys/socket.h>7 m ?& b, h; f/ X
函数原型:
$ k; d: |: D9 ^* A1 o& ~. ^" ? int bind(int sockfd, struct sockaddr *my_addr, int addrlen)3 q0 H" P3 j% Z5 d7 N) }$ B
sockfd: socket描述符: `+ r/ ]0 Z- s
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针4 d+ t* u# j7 P+ m5 C; R
addrlen:常被设为sizeof(struct sockaddr)
! s1 P ^% x- ^6 j3 A
$ ^0 B \5 ?1 m( L; f! H: { 3 connect()
" e- s8 Y, L+ A# D& p1 P. [ 头文件:! ?7 A& ^3 H1 S
#include <sys/types.h>
% D, N; i( N$ V! G3 f7 L: S #include <sys/socket.h>
. @/ X; O# h2 b# [5 O- Z7 i$ B 函数原型:: e0 y& l/ t- F( f% P
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)7 T+ P7 t; ^& H/ `
sockfd: 目的服务器的socket描述符: W& ~- x. k. j5 [
serv_addr:包含目的机器ip地址和端口号的指针" S X/ p$ D8 K+ t
addrlen:sizeof(struct sockaddr)1 l8 w5 }. O3 [6 n7 U) M
' X7 k3 j# ?' k# R5 A( t 4 listen(). v: o) R9 V! C5 k1 ~; Z
头文件:3 k0 l1 M# p# D* w" N/ [
#include <sys/socket.h>+ y" r* S* D* Y: f
函数原型:
# A6 d% w& V# u( K% L2 o' I int listen(int sockfd, int backlog); R7 y7 {/ f* v+ C) X' a( d
sockfd:socket()系统调用返回的socket描述符
( V' J1 Q* D. Y1 N+ Y backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。& ]; J# |) s8 ]# u D. x
+ M u9 w" _4 L$ _. J3 e
5 accept()3 O" n. j/ A5 C7 J/ Q1 ~; P
头文件:
6 j& E( Q/ ?/ R- o6 A, I #include <sys/types.h>0 O- \/ K0 P, x0 c1 D6 t. R+ S8 ]
#inlcude <sys/socket.h>3 K. k6 U5 s% c2 [
函数原型:
# }3 n% o$ U2 O int accept(int sockfd, void *addr, int addrlen)# ]# b U6 V7 {+ [" ]" g
sockfd:是被监听的socket描述符
, n$ V W* y2 o addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
+ e T6 e7 z0 \& P5 d% c* G7 [ addrlen:sizeof(struct sockaddr_in); X" R- |: E+ ?* A+ c- C0 Y+ K
! f% h! }; c, h8 c
6 send(). U e4 x4 p! B
头文件:9 D% L! A) {- {0 m* ` q
#include <sys/socket.h>9 i' k% l2 e: t8 O
函数原型:2 U/ y4 [: e V- g% ~, l
int send(int sockfd, const void *msg, int len, int flags);& k5 T- A' u( k+ l1 A% F% ?
sockfd:用来传输数据的socket描述符
5 ^) z* ~' r' A4 R7 U" G: x msg:要发送数据的指针
: Z( z* m5 w& T6 @3 O* ` flags: 0
! X; N' P' w7 B0 o* g2 Y M / h' O. X: @) l; q# Z# H! M
7 recv()( B2 g' X$ i- L" |! J
头文件:
) a! w* ~& w( Z, i. L #include <sys/types.h>
% S2 f8 Y4 [" a( q #include <sys/socket.h>
/ X5 Y# ?- k: w. }2 k 函数原型:0 d' s- ~: N. Q( i
int recv(int sockfd, void *buf, int len, unsigned int flags)
7 {# A) H; ?& x, b* ~( y/ S! t sockfd:接收数据的socket描述符! y1 ]# S5 o0 n8 d' q. A7 ]
buf:存放数据的缓冲区8 y$ o: P5 f' d" p
len:缓冲的长度# ]) R$ ^" P }( `9 x/ k; A- I
flags:0
" u2 r* K O! Z) D$ N& N) ? c6 f; k1 P! r& u' c. _2 \
8 sendto()
+ c) A6 X J: S0 w1 i 头文件:
; ?8 E: e) E& F7 y6 R #include <sys/types.h>
2 H. {& B; {5 m7 c& y #include <sys/socket.h>$ f2 i& B2 W1 K- G3 }1 ?& N. X
函数原型:4 a/ {/ x s: Z0 t: V# E
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
3 x' J. G, p: @8 A; L. v
+ V0 h. W9 a/ e+ l0 z: _ : m% i+ }4 `+ D' B! @& U( n
9 recvfrom()1 g4 H; j2 A7 G3 t
头文件:1 z9 j6 R) [3 _3 P) j! W
#include <sys/types.h>+ U* H( \+ k) @/ b4 X, j7 n
#include <sys/socket.h>
* O$ g8 k* e: b 函数原型:/ z$ U0 J. G* z1 h3 _) Y
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)
3 Y# m9 q: u" S" ?& r" x
/ @ R K7 x1 Q6 j 4 `' v& r/ W5 `, Q8 |' X) k; I+ H
10 read() write()
0 @: J' k/ a, {) N- [ int read(int fd, char *buf, int len)
1 w. {0 \! j! j' o int write(int fd, char *buf, int len)/ ^" c: y- O& S+ k& h
& m9 E5 Y5 W) L# |1 B3 a! }
11 shutdown()- ^9 m$ B9 z% ^' L- B0 y& r: n
close(sockfd)
4 y" O& W, W$ A7 _, U- U5 T; s# S int shutdown(int sockfd, int how)6 {" z# C" ]- @: y( P* I8 @1 N" g
----------------------------------- [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等)
+ m. A) k& y) K) n& f1 I7 q<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
* ?6 \) m+ r4 K [<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()2 }& c8 ~: B2 `8 Y t9 r
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
! I6 T. k" v1 P7 w<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等% j8 w, o( E+ d5 O
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
: V" Q6 z% r: I7 Z<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件
8 a& {: D7 o, Z) y
! a* t; N/ k3 u" K: c% m# X[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
M* E& g' ~9 {# I3 W6 O#include <sys/types.h> ( o* H) y' g3 s }; n }
7 k' n$ K% D( p" l Y9 `8 x#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons& J6 {2 [5 u' p% K1 {
#include <poll.h> //poll,pollfd
: I, D8 \& T' J- b9 s# n& m7 O#include <arpa/inet.h> //inet_addr,inet_aton
: U9 B3 N3 W* C4 m! }5 C, f7 A, \. [#include <unistd.h> //read,write/ a# H, Q( b0 z" {
#include <netdb.h> //gethostbyname
2 _1 q4 J& ]3 C5 g
0 _4 d/ q7 _# D! C4 C#include <error.h> //perror
1 Q3 E5 ]( @* ^#include <stdio.h>
* y* y t* P; D1 A0 @- X: H- e# B#include <errno.h> //errno
9 c& U3 E; S, r" u. u: }
; u- _- Q) { O+ c$ f) i# z#include <string.h> // memset
" \8 ^( d0 ~2 E+ x$ P* o/ b#include <string>) u9 o1 s5 ]* S6 u- L4 M# S
#include <iostream>
5 K3 J$ r: q# A8 \- d" y7 ?( w& L; U. b3 s( S3 `+ _3 m: w4 C
|