|
[size=13.3333px]一 三种类型的套接字:8 R+ f- Y7 C" x+ \1 s
1.流式套接字(SOCKET_STREAM)$ f- F0 W3 d6 ?( N! y0 e( m
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
! H; c2 @# [3 Q3 ?: W2.数据报式套接字(SOCKET_DGRAM)- i! a: |) O- U. _/ i0 p
提供无连接的数据传输服务,不保证可靠性。4 r6 f- s7 \0 ]4 H# E" ? n8 n5 w# E
3.原始式套接字(SOCKET_RAW)' K0 s! _4 Z! v, ?5 n! J. P
该接口允许对较低层次协议,如IP,ICMP直接访问。
$ y& f5 o- b. S6 D/ q0 @( {( g3 T8 I
二 基本套接字系统调有有如下一些:7 Y+ J+ l1 l" J9 J4 N8 h( K& n
创建套接字: socket()- p( O9 d& b. b1 ]3 B% ~! t
绑定本机端口: bind()
* G- ?3 T. j5 g% T. M: b 建立连接: connect(),accept()+ j) E, B) {7 Q
侦听端口: listen()2 I! e5 M1 [# M% U/ E: O9 q" I
数据传输: send(), recv()
6 v; C0 d6 F# S/ M 输入/输出多路复用: select()$ m0 D5 s2 [% \' `
关闭套接只: closesocket()6 [$ a" F( b, K6 L$ Z' y* i( e! ?; f
# N$ Z1 h+ |+ ?2 y* R2 ]) a/ u! ^三 数据类型
" r' E9 t' n: r, x struct sockaddr& s* `7 k7 `: L6 j6 |
{4 p- B0 A& b& B9 r) z, l+ [" g2 D5 d
unsigned short sa_family; //地址族, 一般为AF_INET
; _+ @) F6 W+ W1 E Z; m, w# e char sa_data[14]; //14字节的协议地址0 L& t; Y3 R2 m1 Q
}
$ V; C& h% u3 F
, k2 Q( p+ k8 c struct sockaddr_in
; e6 g- c, Y2 e6 P {
6 N: B$ p$ [3 \8 W short int sin_family; //地址族2 {! T. t# ? F+ M3 d7 Q* W8 G; P( [
unsigned short int sin_port; //端口号' o( `2 g+ a. Q1 k' h1 }8 X4 r
struct in_addr in_addr; //ip地址" Z# C/ C/ c* V k
unsigned char sin_zero[8]; //填充' _7 y# a$ ]& D: g/ y& z
}
0 r7 M, |# F7 Q6 |/ d" ]9 ~1 ~4 A+ ]( p7 p0 _# X0 B
四 常用函数 L( t% X* Z( n8 Q
1 socket()* ^8 C9 v: k! U
头文件:
6 S- s9 T+ g! [' X: X( o+ u2 V/ g #include <sys/types.h>+ O g' g6 e' i, K! D$ ^9 z! V
#include <sys/socket.h># a0 V" ^9 j Q7 Z/ y6 ?
函数原型:) e# H8 N$ `3 ]4 V* `4 B
int socket(int domain, int type, int protocol)2 `( u3 s9 Y4 v' M/ P# ?5 m7 |
domain: 协议类型,一般为AF_INET
, n" s( U: b6 g& T* U type: socket类型- N% @7 r% N6 X8 m
protocol:用来指定socket所使用的传输协议编号,通常设为0即可# ]9 H% ?& ~8 ^) V _4 a4 I T
: D# _7 O6 R8 v2 r: C
2 bind()
* f) R: N" U; J, q8 Y6 l: t 头文件:
. G; H, b! t1 l, { ?% p8 }" x/ L #include <sys/types.h>" ^/ x. |7 H5 X7 |) B8 p
#include <sys/socket.h>9 Y3 r. b; s, {" Z! o c* d7 e
函数原型:' t( M- ?1 c; b( w, S; q
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)( @0 q) b& S3 M* \
sockfd: socket描述符' E7 R9 D: a! l
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
7 c5 b: Q$ m2 C2 k0 ?! N$ | addrlen:常被设为sizeof(struct sockaddr)
4 _% d- Z/ U% x# ^% d' z1 T
" U5 X2 w- c+ L/ U2 { 3 connect()5 b% ~. N+ R- i$ a, D' J6 I) L) K# z
头文件:
! c1 ~* l7 X2 o4 G* S3 J9 W #include <sys/types.h> p4 F6 X* N$ y5 T
#include <sys/socket.h>0 L! D- ^! A9 I8 `6 B% {
函数原型:
* Z+ C5 D c" u, P5 G4 q& ?; ` int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)" u, D0 T/ j' }8 N% H" f. r
sockfd: 目的服务器的socket描述符
, D, c$ ^$ D7 A7 m2 q+ L serv_addr:包含目的机器ip地址和端口号的指针$ `: [) z# Q) r
addrlen:sizeof(struct sockaddr)
" `2 h5 A/ d. S& ^
8 r7 w. q( @! n! A# r) p 4 listen()6 ?( Z* i& t3 O" ]+ Q; f
头文件:
7 o( P' _ |5 a# H8 m #include <sys/socket.h>
( t, g5 C( C+ K0 b& M. `1 c3 j( Z4 a 函数原型:+ b5 b" y0 ~' X
int listen(int sockfd, int backlog);
4 J4 g4 d! V: n: K4 I; W; G sockfd:socket()系统调用返回的socket描述符
8 N6 d& l+ M- w9 X1 U$ ~ backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。; g. u) Y. E0 k/ I$ g
l0 y0 q7 M7 G$ H
5 accept()# @! p9 F& V" X4 ]
头文件: : G/ ?6 V6 V. m* u0 I
#include <sys/types.h>% J- n. T1 Q1 e- @& W* X" u
#inlcude <sys/socket.h>
9 f3 r5 _3 O5 p! l4 J2 C; b* p) T 函数原型:! d' k' e4 E( E1 R
int accept(int sockfd, void *addr, int addrlen)
: g1 W5 N. f% h5 q9 E; W5 I sockfd:是被监听的socket描述符/ p- o0 \( D& q6 x6 T4 q9 N
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
" {" I. J1 t2 l/ Y8 e& b addrlen:sizeof(struct sockaddr_in)
2 a: F" T; C$ g- W4 {& u9 {) G 4 o1 z: [' C0 _/ t
6 send()
( o8 b o( ]0 n: f 头文件:" g# O* b/ ?" q7 @+ F- X
#include <sys/socket.h>
* g9 u- M2 x: z8 L* a 函数原型:: N, Q; E/ G& ^6 M1 F0 I/ \
int send(int sockfd, const void *msg, int len, int flags);7 o& ^2 O* W/ x& Y
sockfd:用来传输数据的socket描述符: v' L# F' H* s+ Z0 J+ ]
msg:要发送数据的指针 , F/ A' ~% R' S0 M* Z( F* S
flags: 0# ]7 t* R, ]8 N8 z; ]& q# x& v
$ b! g* ?! R/ U5 @7 U. K+ f 7 recv()
) o2 x: g5 X* C, f; y 头文件:
5 {1 c9 V8 N. K8 ~( j: }1 M #include <sys/types.h>5 L4 l3 c* R) g0 D2 I
#include <sys/socket.h> ~, [6 `+ T. B- n1 S5 i
函数原型:! R$ F6 ?3 e0 ]0 J
int recv(int sockfd, void *buf, int len, unsigned int flags)
4 y" r% l0 [5 `/ T* ` sockfd:接收数据的socket描述符
% T- W& K9 b. F/ y4 ^! p8 R( c" D, B buf:存放数据的缓冲区
0 W: A3 X4 g8 X7 Z5 ~: z len:缓冲的长度
% m& X; \) V$ s flags:06 ^4 L2 e1 ~* h+ r- H& J
+ t5 X' f0 U, l L3 e8 j5 g
8 sendto()2 c; T3 z$ T: J, q: ]* |0 M
头文件:3 M" `! o, K1 Z A1 T$ I5 J* u
#include <sys/types.h>
" H) o L2 l \9 S: a #include <sys/socket.h>" r' q; K2 F- M) j, n) }) o. `
函数原型:
0 n' g, m H/ V% r* W4 m int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);3 J) c5 O, h2 Y! e3 w0 X; P+ U$ j: K- z
+ g0 ]: R8 o% ?# C+ }. Z
* |% _, @, u% c
9 recvfrom()1 K& L# S- ]- y6 P
头文件:/ _3 C: V3 E \3 n5 Y2 M* x% j$ k/ D
#include <sys/types.h>, q {4 w4 e" W* q% Z# ?
#include <sys/socket.h>0 b- |5 A6 B W# T! e$ [
函数原型:* h6 K4 J2 j3 j& M% P \8 @% B
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)
1 U+ ?9 k& o8 R
$ g* d) |9 Q/ j# _) c $ o& s, c: j% q5 C, G; {9 I* G
10 read() write()0 R4 W& l+ O% i- Z. }
int read(int fd, char *buf, int len)
% y( S; U. H H5 B& t" L2 v int write(int fd, char *buf, int len)
$ i x8 k* q% Z+ | 4 B3 L$ f, q* g- S }* f* i
11 shutdown()6 {$ v8 I5 q8 F( o# Z) I$ y% h! r T7 m
close(sockfd)
- d$ Y/ M6 @4 q: f int shutdown(int sockfd, int how)
+ q7 _; g& o5 @----------------------------------- [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等)
! [ P) l9 a% O9 E<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等' v( x9 u4 @+ ^. ~" s
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
. G0 x3 q" D5 T4 s3 ]<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等) w! Y& ]) @! \# g: ~* c" _0 m
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等0 Y& }/ J* d- m% J4 R1 r9 S
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等2 |1 g5 f; P; s
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件5 b! P: {' }5 ?$ q5 {. X9 t
- n0 w! S/ [; m% g: f
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
7 I5 Z! j# e. j1 X* B% `. H#include <sys/types.h> , U4 m! J' _: e# H3 ~
$ j' S, o7 E& K% Z#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons/ r; H' ^5 m# E# o
#include <poll.h> //poll,pollfd
9 t& Z+ U" ?! m#include <arpa/inet.h> //inet_addr,inet_aton
7 d$ D) n0 _3 ]$ d0 V. s, s#include <unistd.h> //read,write
$ H5 p* B8 F5 O#include <netdb.h> //gethostbyname
4 g+ `4 k. P; ?* m# P. o
2 r/ y) u3 r( W r1 s& L7 ]#include <error.h> //perror# H4 V' N3 C+ C. X, d m& n. E K
#include <stdio.h>
) k1 U( }% d1 K; k$ _( }#include <errno.h> //errno
4 p/ S# V( k) T/ U7 H* y! M! H# r4 l1 K7 W3 M" O
#include <string.h> // memset
" b: z9 {) s) l" C#include <string>, h- x; v# W" C" L# p/ }5 k' w
#include <iostream>; H; N: E$ W! A3 _. ~; _% X; [' h
7 W$ w, a5 u6 i* m% W. O6 Q: F' ? |