[size=13.3333px]一 三种类型的套接字:
4 T2 {7 H. H+ i1.流式套接字(SOCKET_STREAM)
# h$ d, x! y$ }/ s+ ]& N: g 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
- s& M' Y# @; C5 [! H9 `2.数据报式套接字(SOCKET_DGRAM)% {4 n' q. n. ^8 |5 o2 l
提供无连接的数据传输服务,不保证可靠性。
7 J* b9 o/ d3 R( v3 p3.原始式套接字(SOCKET_RAW)
0 M. L6 i6 D* h' q$ x 该接口允许对较低层次协议,如IP,ICMP直接访问。0 _* {6 p2 T" X! I
; T' G4 \% ?$ |( v4 r
二 基本套接字系统调有有如下一些:! c" f0 c+ M1 x
创建套接字: socket()
, Q: `6 {1 k) a( P4 L 绑定本机端口: bind()
6 z6 d: P/ S4 u3 C8 Y0 y3 l$ E 建立连接: connect(),accept()
# C/ c* s7 O5 K# l* Z& @4 B2 S- D 侦听端口: listen()
' p2 K c* I9 r( ] 数据传输: send(), recv()% I7 [: Y" h$ F# ?2 r9 i( Y
输入/输出多路复用: select()$ z: d' `8 g8 D7 e0 _
关闭套接只: closesocket()
* x* k8 e0 w# \" j) s * J- d# G) t1 H% g9 {0 V& B1 s
三 数据类型6 r+ u7 r3 D! { U% T) ~
struct sockaddr, q* ~# W/ D- l7 \* v# l
{
" H* k9 ~6 _% H. H unsigned short sa_family; //地址族, 一般为AF_INET
) `; N7 @6 g* F" m* n char sa_data[14]; //14字节的协议地址; R# \; k2 W: Z3 p$ y
}
. c: J- }7 A. C$ ~; D. @) Y1 }: W
& c) c7 _' f+ {! G, T* O/ [ struct sockaddr_in% i1 R: i' d( M7 P4 m
{
4 h( ~$ P: Y6 U. N2 ~' H% o short int sin_family; //地址族7 ~# l# {; m X4 C
unsigned short int sin_port; //端口号
1 N7 G; L6 M' T5 o struct in_addr in_addr; //ip地址
d0 z0 ?' C- K* t1 J; t& T3 N unsigned char sin_zero[8]; //填充
3 K' E( f- V/ f$ d* ~ }# p& U4 m; D& g- T v
' o/ j+ m% d' S0 z/ T' [四 常用函数
6 ], o8 @& v% |% N; X' W 1 socket()( Z( V3 S& x( e- I/ v
头文件:
! x& m4 V6 X* [4 e: p #include <sys/types.h>- G3 X ]2 ^6 D
#include <sys/socket.h>2 \) C0 j/ m: N' Y c
函数原型:
- h/ e2 X" O! V' w6 N int socket(int domain, int type, int protocol)
2 [$ B) t. @2 v7 r7 A3 _' I domain: 协议类型,一般为AF_INET
' }$ @$ u! F& a1 b s type: socket类型
1 s4 h8 W" ~- d protocol:用来指定socket所使用的传输协议编号,通常设为0即可! E U, w9 B. H
9 ~$ l+ A# O& r' }2 d9 S& o 2 bind()
; `( Q* L4 J/ T7 g8 w* f" d0 L9 Z 头文件:. G7 k2 b" D. u3 v( N
#include <sys/types.h>
* H, r7 X8 Q/ o @9 S+ Y4 R #include <sys/socket.h>& g N: y/ T: \
函数原型:' G- d' {. Y" z! {# x2 V
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)0 \: [ R: V- _2 m9 F
sockfd: socket描述符. O6 o7 [. L8 m
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
/ C' C t7 t% B! W addrlen:常被设为sizeof(struct sockaddr); n4 R. h7 T; J( a* h, D* G1 d
( a$ w8 j, N6 H0 i3 D& o 3 connect()+ x$ [5 _: I0 i) V0 t/ i& v
头文件:
& L! B$ i! S0 C1 y( g2 | #include <sys/types.h> 2 M# P2 G) y2 C4 Y$ s
#include <sys/socket.h>/ U6 g! Q+ w2 w
函数原型:
, z9 {( a5 O+ N4 j# `9 o int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
" r, l* Q2 ? r* Z sockfd: 目的服务器的socket描述符
C/ ]3 B, ]1 H* o9 w ]" e) @" o4 G serv_addr:包含目的机器ip地址和端口号的指针9 z/ x+ P$ X5 b o
addrlen:sizeof(struct sockaddr)
) F; @% H/ M" v7 N* I: l& k$ U' K% M2 w, K
4 listen()
8 D9 S, V3 k$ l2 f 头文件:
5 I5 i: } C2 J4 W9 ~ #include <sys/socket.h>1 `8 R% L8 x5 w7 \& O7 `3 v
函数原型:
6 R4 \( o% j9 `! B; M& d& ~ int listen(int sockfd, int backlog);
5 d( L1 U5 T' s0 s- Q. K sockfd:socket()系统调用返回的socket描述符
6 N! U- J( A7 H, e c backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。
( b3 Q0 a, W3 s" v" A) r7 f" }8 f N8 S/ C$ J) Z' P: G" D5 O
5 accept()
7 X; X: g R7 W" Z( Z# h 头文件:
$ d$ F S( v5 T& ?2 X4 \) \ #include <sys/types.h>2 L9 {& p0 L( X7 c6 e9 g" W$ \( c
#inlcude <sys/socket.h>
# B' F) F. C; f6 H/ m8 e0 P. { 函数原型:
! O0 o( Z/ I! R' T5 i; T int accept(int sockfd, void *addr, int addrlen)) z1 j8 ~# c: N; D5 L6 n/ S1 U5 x
sockfd:是被监听的socket描述符
0 _, c# z5 x' w; o addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息6 t' P7 o6 y* T7 n
addrlen:sizeof(struct sockaddr_in)
; g/ A5 Q+ F+ T
. V. r: i, K4 p+ g! Q6 I 6 send()
& k% d; F7 \# I& ^# Z% c, ` 头文件:
8 d* x" P2 @% W/ F* }" P3 l. Y) Q #include <sys/socket.h>
8 J8 u/ d8 e8 L* M' _! _$ v+ @ 函数原型:9 x3 x% U1 F9 r, ?9 l' W
int send(int sockfd, const void *msg, int len, int flags);( l' A1 p$ p; e H& n# X! U# s1 q1 ~
sockfd:用来传输数据的socket描述符+ l$ d; m8 v$ w5 J+ u! g4 k. W+ n8 o
msg:要发送数据的指针 * s6 t& _9 I5 J4 x
flags: 0; }( ]0 u( r* P S- d
5 i- }$ {9 J8 Q! b! `/ u 7 recv()1 @& ?5 p9 a" V
头文件:/ I) X: r" J* k% d, I5 p. w3 }
#include <sys/types.h>! w+ l- L+ _6 b$ R" f) ?* K) ^
#include <sys/socket.h>) S8 p2 x: s m6 h8 m( }
函数原型:9 ~$ e- o. E/ S+ q
int recv(int sockfd, void *buf, int len, unsigned int flags)8 H. p6 t& L; Z5 W" C0 E% V) K
sockfd:接收数据的socket描述符
: u. L/ X8 t6 z8 l( L# U buf:存放数据的缓冲区
* l# B/ r! Q* `, D0 A& ?/ x9 j1 m7 e len:缓冲的长度
( w% d8 G$ K1 X v' n1 G flags:0
: \; _, [8 o) W0 L+ U- _ M* ]9 N7 B) x: {8 U( x8 M4 ?6 b$ I7 p) N7 p
8 sendto()
) W! V+ a! a# d& }4 L6 U- y 头文件:4 |$ ~- U7 y; N( ^2 a
#include <sys/types.h>5 x+ A5 f2 F2 O: H3 R f
#include <sys/socket.h>
1 |: w) T( W+ q4 E# i$ g9 W: r 函数原型:
3 T& ^4 {' Y/ S! T! _ int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
; U4 z' b9 V$ ]; J/ z& X5 N+ `0 d4 g - F+ R3 q( J8 Z+ {5 X$ G
1 d1 p* V9 [& Z) z; z- T 9 recvfrom()
. d& r% l v( h# ]: d" ^ 头文件:
+ s, |6 }7 R1 J8 v" `& a, I6 A #include <sys/types.h>8 D9 H$ _+ q( L4 U ~
#include <sys/socket.h>
& X" k ^8 D" [; h, ]5 k 函数原型:9 \ H3 H2 z0 g" p% I
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)
- e1 I4 G! U9 i$ t+ T9 ?. f% h( E) y. B; M/ L
+ v' J% c8 [2 i) F/ T3 l
10 read() write()
7 f! G: E% _( H9 \7 F8 ^ int read(int fd, char *buf, int len)
/ }) n! c x- w4 i) ?9 c int write(int fd, char *buf, int len)! e, w* s0 S6 D1 I6 X5 C4 T" i
9 E$ [% t1 ^+ I4 I7 v2 d 11 shutdown() @" \4 p& ~; d6 J0 g1 z& Y
close(sockfd)
& I* }- X3 E7 s$ E2 o/ j& g. _! m+ j int shutdown(int sockfd, int how)
2 } R. q* L$ _! A----------------------------------- [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等)
( O9 j' f. Z. S<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等# `; k% P! V% o4 u# h g& `" _$ T
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
! H7 U- |% u- z/ [. m% d0 r<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
/ t+ R: Q! N1 P3 x<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等) ~ B9 p1 w2 i
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等1 L, T5 `: q0 u* P+ y4 c5 f
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件 b/ d; }" T2 D
' P9 y+ z+ D# N8 T: L" l
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等* D. l& |; `! J" j! V' E; A& a
#include <sys/types.h>
6 }$ h1 Q) l$ \, X6 y
3 a0 V m; c4 ?7 C6 z#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons! Y8 D% w7 Z" ]9 m
#include <poll.h> //poll,pollfd' T) U1 @5 t2 T. f5 d
#include <arpa/inet.h> //inet_addr,inet_aton1 r# s6 k, f/ f+ @5 V! }
#include <unistd.h> //read,write3 a n5 x5 N" v- L: M( a
#include <netdb.h> //gethostbyname
" Q X" y7 A# G
8 o {0 ?8 @, L6 Y1 f#include <error.h> //perror6 r) W% y& [( b' N( I7 b( A
#include <stdio.h>
$ v% ^) |# v" p- l3 s#include <errno.h> //errno
4 Z7 v8 S$ n' `
0 R, x* J) A/ k9 T! Z( M% i' G' Y r3 G#include <string.h> // memset
& e: _3 r1 A& T5 s; ~1 [#include <string>* Y3 I' {. ?. I! W0 l& z
#include <iostream>
+ s, c- {4 b- Q2 y6 O5 C3 E
, t s: _- q% z, z |