[size=13.3333px]一 三种类型的套接字:6 L, F! ~ H8 f$ [9 Q
1.流式套接字(SOCKET_STREAM)# F+ c. L+ T/ R. R4 q3 R% y
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
+ l& F2 f. e' Z4 t4 T2.数据报式套接字(SOCKET_DGRAM)/ @: w! N% \9 Q2 V8 y9 r8 Y# P
提供无连接的数据传输服务,不保证可靠性。7 U4 ]7 N% h9 e2 `, S+ u* z
3.原始式套接字(SOCKET_RAW)
w5 p5 j, z; l$ } 该接口允许对较低层次协议,如IP,ICMP直接访问。
/ P& K' O- v( ^. E
% K1 m. T, i" \0 y# w7 q0 R二 基本套接字系统调有有如下一些:9 l/ @. l& w F, ]5 ?1 d, i' k
创建套接字: socket()
+ n5 Y+ M! y9 ~6 G: P$ l& W; O9 n 绑定本机端口: bind()7 t: @' {6 z { y- L' M% P
建立连接: connect(),accept()
6 a: H$ W/ X2 C0 D) B8 r 侦听端口: listen()- {) {8 Y6 [7 |9 X/ R5 s W
数据传输: send(), recv()% \' @4 F( A) j! l( U/ m
输入/输出多路复用: select()
- G5 \: T. y* t6 Y, ~9 k 关闭套接只: closesocket()
Z6 w6 X% F' O0 T3 ^& ]9 [% \8 ~3 K
$ Y9 P- o& Z1 R4 u- k5 Y4 Q三 数据类型
; U' Z- S: n8 \$ C struct sockaddr1 |4 ~' n2 \3 x# Q
{% h/ b0 i# }5 c! z7 U' q" c
unsigned short sa_family; //地址族, 一般为AF_INET" ~2 M v3 M: ^7 ^6 @& l) q
char sa_data[14]; //14字节的协议地址$ A( d: J6 i0 @1 N" v
}' y0 s' g' K) b
- X3 U: `" P! y! S, `$ ?2 O
struct sockaddr_in
2 w/ y/ J4 A2 `9 m {3 U' R4 f! B+ r) u5 V$ D/ H2 s" @# G
short int sin_family; //地址族 Z: e: Z4 x! J( @; A% | s
unsigned short int sin_port; //端口号5 H5 [; P" U: K* i# Q
struct in_addr in_addr; //ip地址. U2 X6 }$ p2 B# Z6 }, o% Q
unsigned char sin_zero[8]; //填充9 }, r7 H' w" V) w8 z/ S4 g
}
$ Z& l2 }5 K: r4 F; w; B5 i
4 \8 o* Q: Y A+ c" b四 常用函数
8 W7 j! D% o% j6 s& ` 1 socket()
* j- V3 E$ y M, ` 头文件: 9 t7 l4 W7 f& f# z Q, u% h* S: D
#include <sys/types.h>
* d: U ?' q* c1 G# y/ p; k #include <sys/socket.h>
# _8 u( ]6 j, b2 y. _ 函数原型:! x( G& e( }) [) C) [% E1 L
int socket(int domain, int type, int protocol)
4 w% C n( X: m# E: ?( u) c0 n domain: 协议类型,一般为AF_INET
$ Z# d9 b9 i3 k% b type: socket类型2 s; j' \! |. y1 B6 |4 X
protocol:用来指定socket所使用的传输协议编号,通常设为0即可
, M' @( p/ ~( x* f- e! y6 R, x( p
% n+ y- d9 ^6 D* q 2 bind(): Y& T9 y* d9 t& Y2 K' y# h; ]
头文件:& e' P) b$ n# t: A% b" I: \( {2 q! l# d
#include <sys/types.h>; h+ ^% t/ R% Y; n/ d
#include <sys/socket.h>: K8 g. W# h% F# I1 f% U
函数原型:% a% U# e# Q+ o+ Q; x, F) C
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
- X2 V, o, k2 G$ y* } sockfd: socket描述符, D; s" t K# R9 T" Z
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针# U/ Y6 v/ K, `) v0 i; j
addrlen:常被设为sizeof(struct sockaddr)
' B2 L. S" m; m* L( m4 I7 `, A& D Z9 M" D% |) l i1 ^9 N
3 connect()2 q) N6 f4 j( F6 @6 I
头文件:4 [ P5 Y5 @" R2 ~
#include <sys/types.h>
' t) M# n b: S) Y- H" D0 r1 x6 U+ x0 | #include <sys/socket.h>
% b9 F6 T3 m- F2 q/ [* A$ y" W; X 函数原型:" e3 s0 h; Z2 ? U' f! F, z
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
: S, b& H' g! J( ]8 Q/ `! c$ D4 h sockfd: 目的服务器的socket描述符
, H& I- ^ P0 V( \- b+ F, J serv_addr:包含目的机器ip地址和端口号的指针" _1 [ b3 O( {4 g0 p! u [
addrlen:sizeof(struct sockaddr)! p3 b6 @) Q+ |) A+ \1 N
" Y5 w6 U6 e2 Z: v6 G8 B+ H. w7 m 4 listen()8 S/ T' z) N! H* k/ [* o
头文件:
0 C# B# A' W% Y #include <sys/socket.h>
% r; m3 g8 o: K, }% O# \ 函数原型:# N3 Y! |4 C- R, X+ r1 l/ }; k
int listen(int sockfd, int backlog);/ Z2 u' R- Y7 [; K7 U( i% I: n5 U
sockfd:socket()系统调用返回的socket描述符
. n; J' L k% U: B! M8 u8 C, T% y backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。
3 ~$ N0 M( ~* s8 }4 |
' U/ F; H. l- `9 @0 _ 5 accept()
0 d% q+ m2 Z+ O 头文件: ' i C, _0 \% S" F+ D. k9 d
#include <sys/types.h>
! c4 _9 x, y9 j; I" E #inlcude <sys/socket.h>
. }: Z2 l$ g3 X2 } 函数原型:
2 c9 ^2 z/ s% O# f# L int accept(int sockfd, void *addr, int addrlen)1 i4 X# w+ Z- B3 g3 K! ]* h A8 h
sockfd:是被监听的socket描述符" K! Y# a' Y$ } {
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
) p+ I/ d! ]6 W1 v5 H2 Y# b addrlen:sizeof(struct sockaddr_in)) }: q" G3 K4 C9 h2 G
8 W& |% A3 _/ r% X4 ?
6 send()
0 ~, j7 T& W" @' ?" I 头文件:
/ w5 ?# ~! k& r, n s2 t% ` #include <sys/socket.h>
. b% l6 e( P# f6 x& f q& I 函数原型:
" q1 r3 @* x& t7 g! L int send(int sockfd, const void *msg, int len, int flags);& V/ P& d5 z! U/ A, t4 N& u. ~
sockfd:用来传输数据的socket描述符
6 C2 V- e; H8 i/ E6 k msg:要发送数据的指针 0 \2 R- R0 q* l0 \4 S6 @
flags: 0
( z6 B7 o7 O; P7 }! |
# p$ Y5 ]% _" U 7 recv()/ R) ]! C0 C# \6 Y& x
头文件:
4 F4 W+ a, U1 j3 @ #include <sys/types.h>
, o8 b8 J( N- c2 O' B$ O3 s8 Q #include <sys/socket.h>5 n1 ^ g& p/ S, n# ^; g
函数原型:8 ^7 N. h! w1 t4 x
int recv(int sockfd, void *buf, int len, unsigned int flags)- k! a, Z+ y6 n6 h1 F
sockfd:接收数据的socket描述符# m' W7 Q$ l4 b+ n
buf:存放数据的缓冲区$ j5 ~+ m9 ~4 s1 w
len:缓冲的长度/ d: y. |4 N& L) j) c) _1 k
flags:09 s# ^* ^+ O' O; E5 u5 n
4 s h1 Y m% f
8 sendto()$ y7 f: S2 a; L& ]7 d" a
头文件:; T5 A* H: J" I, E1 o
#include <sys/types.h>% r/ q) X: c H) R& g, H- [
#include <sys/socket.h>
0 w4 [: D4 m5 B e5 d6 j8 d7 ]5 d 函数原型:3 j/ [+ O, P- Y; V* O
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);, q% W8 J) P+ F/ r& ~, j: R
, N6 t4 M- @; c" j
2 A( a V6 @/ S6 w
9 recvfrom()
" @1 Y, `! ^. H 头文件:
- g" g K2 e5 o4 U5 J" D. m #include <sys/types.h>+ N/ e+ N6 K2 |6 E; p
#include <sys/socket.h>
$ n) h7 j, J" c. e3 v 函数原型:
, S( @! n% U; g int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)3 o1 f" Y) o1 J* t+ l0 n
, ^% M. k/ \$ a2 ]4 E
" w/ _# Q6 v" T8 O% Y4 R 10 read() write()
6 _% H) y) c x* L$ p: n int read(int fd, char *buf, int len)
& W! s# h$ y2 f6 p( i5 _( o int write(int fd, char *buf, int len)5 O! ?0 n9 e* f |
" a' w7 }" A& Q6 x4 T, D 11 shutdown()$ @, d" H, d/ Q7 c. S( H" G
close(sockfd)( H3 i! X* e: H! B! N' p
int shutdown(int sockfd, int how)
) w- i7 y8 B2 {& i R& c----------------------------------- [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等)
- r2 G0 y' K, x9 V; Q& ]<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
' v- K# g4 c5 v$ n<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()6 d9 a9 r- X& W \9 C
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
% A- q/ y2 D' z9 b+ R<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等, ]) i$ s7 R+ |$ d9 \. J4 C# W
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
6 J, n% Q3 ^, X7 s, y8 `<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件
8 ?- j* Z: ^2 M6 }1 h D j5 ?* d7 i1 ]2 e H/ K
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
) X: s* {$ r6 k, w* H# `4 V' Z#include <sys/types.h> 7 h8 Q/ B: [5 C; R8 n
& H$ Y0 [7 y3 W& \#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons% F+ U5 q1 v8 \ U* S
#include <poll.h> //poll,pollfd
- J \# P/ Z: u$ ]#include <arpa/inet.h> //inet_addr,inet_aton
* W9 R$ b1 e8 V' C9 D5 y" o: H#include <unistd.h> //read,write
- b5 N; R$ V( X) y#include <netdb.h> //gethostbyname
; r) K) R; _3 \4 r7 S5 M- E8 v2 V7 P S
#include <error.h> //perror& k, p+ w5 d( G% F4 v4 C7 h
#include <stdio.h>
6 ~* B0 t6 T: g3 c#include <errno.h> //errno3 T( {" H' q3 B1 L. o/ y0 z( J
8 ~" {1 ]* h) {/ U9 _( \
#include <string.h> // memset& E: T/ P5 [0 @; l
#include <string>; \$ h! I! T/ A+ q' s- u* p) r
#include <iostream>. k2 ] u% ~7 S& ?- ^% D: i
5 C) T& t3 b: H |