|
[size=13.3333px]一 三种类型的套接字:9 }: B& o/ {5 z! j( u4 J
1.流式套接字(SOCKET_STREAM)
+ R! d2 m$ q/ Y) Z# v, H 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
& U4 B. D |6 d$ C2.数据报式套接字(SOCKET_DGRAM)
) g/ A+ g1 M5 u2 R" x1 P" d* g# ?: x$ ` 提供无连接的数据传输服务,不保证可靠性。
$ r, ]( G/ a! B7 E6 c3.原始式套接字(SOCKET_RAW)
: }+ d9 e, t% u; S 该接口允许对较低层次协议,如IP,ICMP直接访问。6 ?# C. K8 b3 u/ R
6 ?. z( F7 v$ g7 n: P二 基本套接字系统调有有如下一些:
! p2 y( s9 w/ ]5 Y( U4 d8 w: P 创建套接字: socket()& n8 J' @5 P* H/ z+ ?, M3 r) h9 f" ?
绑定本机端口: bind()7 P8 T5 b6 T$ ?" {- @
建立连接: connect(),accept()
& q+ I. ]* a( F% m 侦听端口: listen()9 c( J* x6 X* ^5 \- ? j
数据传输: send(), recv()
8 Q- u3 g5 N/ G 输入/输出多路复用: select()
& x! R% _0 T, t- \+ l, m 关闭套接只: closesocket(): x7 v& h, v6 ?* v$ [/ w
! j c( u) O [0 {( G
三 数据类型
. x% U8 i' B8 \* f% Z& {; d struct sockaddr
" K7 M+ c% H6 P. h# T; n1 A J$ U# O {$ X* L3 x2 U7 O% D
unsigned short sa_family; //地址族, 一般为AF_INET
4 p" o+ S4 B0 M' A. E char sa_data[14]; //14字节的协议地址5 j C; M. }4 V, p2 \
}
3 n5 K' b3 C2 |" D" G
9 u% a! c/ t; s8 H& u s* i struct sockaddr_in9 u9 ?7 O+ \9 R7 u1 Y
{# g% I3 m6 ^9 @ |, m/ T" h
short int sin_family; //地址族, ?/ Y4 C* {! h8 G
unsigned short int sin_port; //端口号: l3 E6 o! }& G; S
struct in_addr in_addr; //ip地址
, m4 |5 y+ H& V- [% g unsigned char sin_zero[8]; //填充: ?2 O9 h9 ` K* j! U& a$ I3 t
}& y+ @: a1 ]! v# W- j
/ V: @! R) B8 ^9 ?四 常用函数( d+ X' W0 D, Z/ L8 r: @+ q
1 socket(). `# Y5 X/ X1 w2 N' c! I+ }
头文件:
- B, E7 E0 t/ g) n- b% `7 N #include <sys/types.h> h8 M8 x e B% J
#include <sys/socket.h>$ x0 c+ |8 D4 S3 \' d
函数原型:
' G/ h3 C h: w int socket(int domain, int type, int protocol)
( q+ I J" @8 U; E; B$ ` domain: 协议类型,一般为AF_INET
% \; Y, v i8 i8 S$ H( X type: socket类型0 p/ h' F- }4 E
protocol:用来指定socket所使用的传输协议编号,通常设为0即可9 o" P* D Y+ D& H, g
7 \- u( L0 b& @5 d, q' y4 i 2 bind()
5 k3 M. u0 R; D9 s 头文件:
r/ z1 G B% h1 {! F #include <sys/types.h>
O/ d9 e8 ?$ Q #include <sys/socket.h>
& J- V6 g8 [# k" V$ L 函数原型:
' x; T% z# y+ _, D int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
/ h l. V h& t" l& W3 E sockfd: socket描述符
( P/ N! g( O% Y; a my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
+ c8 B$ U# n, L$ |& F2 l addrlen:常被设为sizeof(struct sockaddr)
1 ^+ F2 e. U1 H
5 N+ M4 o2 y$ y/ Z+ R9 g7 t9 O 3 connect()
' I3 ?; R0 a E- L, G0 \% f$ c+ E 头文件:
( \. ?5 [7 r7 P& l( P #include <sys/types.h>
2 p; G3 X. W& D$ y# m1 X) j- { #include <sys/socket.h>+ W% _, D$ m1 }4 V! B' v' K- Y. X
函数原型:
" ^* {" i# p5 \1 x$ d4 | int connect(int sockfd, struct sockaddr *serv_addr, int addrlen): M, N; u+ |2 K3 A
sockfd: 目的服务器的socket描述符8 M+ I: P0 Q3 p: F$ B+ K
serv_addr:包含目的机器ip地址和端口号的指针
! L$ o3 T) \6 o9 h0 u1 l addrlen:sizeof(struct sockaddr)
1 d H) `. R- c& \! ~0 l. l. h
0 ~* i2 I- F& M' ? 4 listen()
) y& S+ s1 C ?; ?+ Z# f$ K/ a: p 头文件:
4 N2 A. O9 S5 M% V #include <sys/socket.h>1 s& T' o" Y' d, g% Q
函数原型:: v5 h4 h+ @: v2 k4 w% o! O
int listen(int sockfd, int backlog);
* c Q: F5 y4 K. s$ r. S+ V sockfd:socket()系统调用返回的socket描述符
9 y# E1 |% b R backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。0 o; D$ P T ^% m
" t0 U5 W: [ C2 i; }/ m9 v/ h
5 accept()
. h1 T3 J b0 L; I7 [ 头文件:
% Q v9 P Y7 ?% d #include <sys/types.h>; v/ f, {! j2 Z; D
#inlcude <sys/socket.h>
$ @5 q1 D. f+ Q; Q$ T' ~# [8 O 函数原型:
$ h5 @ X. u( z$ j5 s, Z4 g int accept(int sockfd, void *addr, int addrlen)
. |% M) f' G- A$ a1 x0 r- I sockfd:是被监听的socket描述符
. k. v0 G0 `7 J4 U2 J: ~3 T* C addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息5 b1 s b/ l4 h( L: o
addrlen:sizeof(struct sockaddr_in)
9 Y6 E3 {0 a' t1 j' c- [* Y 5 i0 H: A6 R8 @" E9 u" o0 `# h
6 send()& T) L- I8 a2 h7 m& q# u0 E3 F4 s
头文件:6 Z1 y5 o; }; O1 ^
#include <sys/socket.h>' }8 o a7 u9 Q8 {# k) I6 ?
函数原型:
, Y! U2 i! K$ D# B& Q* c int send(int sockfd, const void *msg, int len, int flags);8 Q9 Y! P+ e1 T+ z' @) g- ^
sockfd:用来传输数据的socket描述符$ p) b! A- G1 G7 m# h/ q" n
msg:要发送数据的指针 ( [! |* ^& P* e9 }1 ]
flags: 00 G; p+ W V# G; q3 o ~) B( [
, ]. W" [9 W. s* h+ Z7 U+ u6 z7 t% m0 G 7 recv()
: @; J0 l- J. a 头文件:7 E9 ?9 G1 \. C$ X( ^
#include <sys/types.h>
9 R9 {6 `9 u: q0 l9 x: R6 e% }" X #include <sys/socket.h>
: [/ q- L- m2 R8 i& m# o0 a 函数原型:
0 B0 l3 X9 q0 C* W- a+ G: g int recv(int sockfd, void *buf, int len, unsigned int flags)
- s# A- e( K6 j0 q2 P sockfd:接收数据的socket描述符$ P" O8 l1 z! Q# a; u( v9 y5 t0 G
buf:存放数据的缓冲区
9 V* x8 u/ c2 K# P" X len:缓冲的长度
: J+ w: c& g n3 o$ V$ t flags:0" {- G( d+ Q+ t
. d( }: \2 k7 B7 P: _! L' v
8 sendto()" Y* c( R: `, I# ]
头文件:
$ W2 E( J: u' ]8 r2 ]# X #include <sys/types.h>/ L# p) [; A2 g, ~; U% F& f) L& l
#include <sys/socket.h>
0 f8 s! A/ B& {& t, f6 i+ o5 t 函数原型:) X* w& C- H3 Z/ M) V
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen); a' `2 ], P3 v
K3 }4 w; b* p) R2 a2 T ' p& m6 n7 }) [& ~5 l! G) R
9 recvfrom()
% q" h( L4 O$ L6 c 头文件:
, n, e3 O' Q2 |! V) z* u* g #include <sys/types.h>
* ]9 H$ k* D) z8 J3 u #include <sys/socket.h>5 }2 E2 Z3 }& K
函数原型:/ V! }% ^" P8 j6 O) e
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen). x5 L. r; P* R+ f+ n3 o: |+ h
7 H J- I7 e( e9 g! ^( o0 c
$ K7 |0 K/ \$ _ 10 read() write()1 R. m5 k3 W* m* z9 I
int read(int fd, char *buf, int len)
# _8 L6 C) E4 Z8 q7 K! O; N int write(int fd, char *buf, int len)( A; e1 I* ~' z `, C
' m" l- x9 N7 p3 i3 w; o& L
11 shutdown(), F/ ~, v5 _9 k- ?" e8 f( Q5 \
close(sockfd)$ A$ S3 ]8 H" Z% v- r
int shutdown(int sockfd, int how)
) O# }# L$ m$ j' B! w, ?----------------------------------- [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等)
2 t5 Z- a0 ^. F( X) ~6 d<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等4 ]/ C( a3 `. M# ]! H- t
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()6 M: f. v' k1 {% t0 ]$ c8 D
<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
# {; d0 K! n7 g# W<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等 u. ? j. u4 W+ ^0 W0 ]5 H/ l
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
# k7 X' h @- F Q$ u<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件
" S. g w6 ~1 j1 _. \# |! |
; c. w3 v! ~3 F) {9 ~; q0 M7 G1 X7 r[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
5 z. t5 N7 d& z; ]% r( g' A; N#include <sys/types.h> " ?7 F2 Y+ G5 \, g5 Z- d9 F9 ?, e% i L
+ f/ I+ t$ L/ B. V9 Z& c
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons; A3 Z# e ~& K3 ?
#include <poll.h> //poll,pollfd4 Q6 f( p5 W* B2 U+ }
#include <arpa/inet.h> //inet_addr,inet_aton" q: a: X/ H, Z6 {* g$ R: j1 a9 ^( l
#include <unistd.h> //read,write
2 P0 |4 R5 U; K @#include <netdb.h> //gethostbyname% T) H( l& M; F# m
" T/ h& }/ x6 R" o: R#include <error.h> //perror
* D$ Q$ s. F, {: o! c, C#include <stdio.h>- f: K+ B" T/ L8 p( A }. D5 ^
#include <errno.h> //errno# ~% Z1 [# P0 _% \# l& C Q& p+ `
" O$ C/ @& D9 K( w#include <string.h> // memset& Y, [% T1 K3 l1 M) d$ }7 G4 a
#include <string>
" [" N3 X' [' M+ [ @, \9 k+ I#include <iostream>7 M/ @/ C, K. S6 G6 G
- W- i* O2 ~0 [% ^5 e$ X9 w
|