|
[size=13.3333px]一 三种类型的套接字:0 [0 E6 V, j2 ?, z; D1 ]2 X! S9 a
1.流式套接字(SOCKET_STREAM)
$ E( a6 Z% b/ m) |" B( O 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
/ z" R/ ^- i+ {' r9 ]9 D2.数据报式套接字(SOCKET_DGRAM)" x1 R3 `( C3 ~6 k( @0 u2 l
提供无连接的数据传输服务,不保证可靠性。% }; \7 {4 I W: R, e
3.原始式套接字(SOCKET_RAW)
4 Y4 P) l! V! S0 h( \3 W" ? 该接口允许对较低层次协议,如IP,ICMP直接访问。4 Y" D- g. ]4 T- p, P. C2 G9 y/ P
" k4 U$ _+ }2 v7 U3 j9 u二 基本套接字系统调有有如下一些:
% b2 v' Y8 _% |, ?( h. Z 创建套接字: socket()( C9 X8 N0 U2 X. ^- ?7 E t
绑定本机端口: bind()2 p6 y/ r$ u2 H4 h
建立连接: connect(),accept(): V \9 U, j, g( K; |; K' M
侦听端口: listen()
) l5 _6 a& I+ T0 v1 H; z, \ 数据传输: send(), recv()
5 g$ p5 x& _% y T2 h# i1 u; z9 @ 输入/输出多路复用: select()
# B |* l1 f% I' Q5 ` 关闭套接只: closesocket()
* `; e6 l# N5 [
% g S7 W; S2 z: y6 Z! \三 数据类型; m% H1 W8 n! Z: Y% }8 }* G/ r1 c
struct sockaddr
, A2 Q( C7 O' i, H+ `6 K {) y% J, c( x5 k4 ^$ ^
unsigned short sa_family; //地址族, 一般为AF_INET
; f e* Q- r' c* W) G0 N char sa_data[14]; //14字节的协议地址% R8 A% ?" U( P" Q8 t8 |
}7 u& y" q9 F, m% J" B; C% {/ ^
! z; k, Q* a" l# ] struct sockaddr_in+ _# x9 _4 u2 s/ F( B0 W+ r* X# c
{3 Z! t& }% q h% N' G; y$ {4 I
short int sin_family; //地址族
2 q9 w# W/ s- x- ? unsigned short int sin_port; //端口号
& f( R) P, R) W( @ struct in_addr in_addr; //ip地址
8 v9 Q: U* F3 Y1 X/ Y. h unsigned char sin_zero[8]; //填充' Y3 ~5 w$ |" S7 B4 O+ Q; O' ]
}% J \ K0 U; M6 V, Z+ m% _. N
}! P7 ^( h' ^7 g四 常用函数
* u! s3 O: D9 s9 o% f8 V2 e) O6 M 1 socket()3 ` x* ?: D1 j. d: [6 F
头文件:
: P+ ?1 a! S6 R: B6 C2 x #include <sys/types.h>' i+ L+ c% o& H/ U
#include <sys/socket.h>, e; y& F& |( s
函数原型:: E6 |! j0 H* K) S
int socket(int domain, int type, int protocol)& F1 j6 ?$ o) R
domain: 协议类型,一般为AF_INET8 ^" s4 y$ \# h$ H% s |
type: socket类型, y' m2 W% x/ v3 } ~ y
protocol:用来指定socket所使用的传输协议编号,通常设为0即可, F- x, {2 z5 G7 [0 _! h
/ l; _6 ^/ o1 O9 H5 S
2 bind()
H% z0 b& p+ u" a1 G* S 头文件: Z5 j" R. P' u" F' m; k, u
#include <sys/types.h>6 w8 o& `& A0 Y+ x4 U
#include <sys/socket.h>) M9 `. k' d/ w; P0 l
函数原型:
. H, N+ H+ t/ k8 U) S4 k/ v int bind(int sockfd, struct sockaddr *my_addr, int addrlen)2 G, a; V) z+ u/ E1 O3 L4 @% t
sockfd: socket描述符
) t! S5 d( V5 r# t$ Z6 j4 [ my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
( e- P8 i4 ?9 u' w" O: T: [ addrlen:常被设为sizeof(struct sockaddr)7 C) q% o$ Z9 x4 r/ T6 i9 U
- W1 H3 G0 }+ O1 {3 M! ^
3 connect()
+ S, f/ A i( h1 q* n4 B4 R3 x# o8 K3 E 头文件: }' |% c/ T* m0 s7 z
#include <sys/types.h>
; @* S* S# {3 R& @' a: J2 C #include <sys/socket.h>
0 {8 h" k Q: Q3 s/ D2 i0 v 函数原型:
% |; M; {+ U, o6 c* N: Z& U int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)- S, O" _! X4 |1 H0 u+ y+ Z; k
sockfd: 目的服务器的socket描述符- Y% y5 F% |! @2 G; [- |
serv_addr:包含目的机器ip地址和端口号的指针
3 K7 P+ x2 Q6 a! w6 S1 M j( }' x0 r$ }5 g9 m addrlen:sizeof(struct sockaddr)
) q5 t4 x$ Z& `6 l9 e- u! O1 m( M* s3 o( }9 a8 H0 d
4 listen()3 ?; a6 f) q2 i
头文件:
! ? F& |9 {( R+ h$ `4 t6 i #include <sys/socket.h>
3 B$ S1 J: W* D5 q# Z! D3 Z' l 函数原型:& C( u1 N, N# {. ^$ ]5 D
int listen(int sockfd, int backlog);
2 j" F3 y# j6 a sockfd:socket()系统调用返回的socket描述符* T: l, d) H% H3 V" p1 M: F
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。9 O1 P' h. Q) r# `: |5 L% v
~2 C4 g% @5 K, m/ Z 5 accept()
. B$ I% S2 J T8 Q9 m% m; Y 头文件:
. Z6 \( \% m# {* I #include <sys/types.h>* j& @3 Z0 W# P2 M$ J
#inlcude <sys/socket.h>
& A8 U; B a* V! s {3 S 函数原型:1 ^" C9 R2 ^. I# o4 f
int accept(int sockfd, void *addr, int addrlen)
% W% I' h; z- t% E) s( @& R sockfd:是被监听的socket描述符
# `4 a" x1 X3 o+ u1 x addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
& y+ ?9 |) B0 H \ addrlen:sizeof(struct sockaddr_in)/ j/ b# Z) x& J. |$ L) i
; M5 Q" e) @ z
6 send(); h7 K" U3 c2 B' c
头文件:
# V8 g' @( X) |4 [ #include <sys/socket.h>
8 m5 G/ o# Q2 t' C/ Y 函数原型:
2 R ?/ t! C! `4 g" l0 U8 k: g2 I int send(int sockfd, const void *msg, int len, int flags);* Y% M z8 o) ~) ^1 y8 u$ R
sockfd:用来传输数据的socket描述符/ Z0 U7 L" |' G; c) a* `4 u
msg:要发送数据的指针
% [- ^8 Y6 h" ~. m* m& Z) d3 u flags: 07 s# t+ z5 z$ F4 [0 U2 O$ O
5 X; j1 Y8 _1 ~, y 7 recv()
; x. v5 `4 u X% ?6 D$ F 头文件:
+ Z9 S" E2 D# ] #include <sys/types.h>9 @, Z) _& g3 t
#include <sys/socket.h>
0 s- [) z# {( P2 H 函数原型:
u) r. h& S9 W9 d int recv(int sockfd, void *buf, int len, unsigned int flags)
4 s2 i/ a" g$ a2 Y+ e sockfd:接收数据的socket描述符
0 r$ ^2 k9 C5 L* r. f buf:存放数据的缓冲区- K1 S2 A4 O m f6 m! k" [
len:缓冲的长度/ p6 J4 R2 g" |1 C" ]
flags:0
+ C0 L$ V z! X. L7 C: B- j, d1 G: [" a' g* D" z; T
8 sendto(). j+ U- y' k) m) w% a" q
头文件:
4 O K4 {# M$ V! g+ f; [: H #include <sys/types.h>
6 X' v% y* X: T0 h #include <sys/socket.h>
* k+ u1 U S6 q 函数原型:
9 e% r, i. G8 H" A int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);: I: u' k! W: ~: L5 W0 M3 M& t# x
" v1 E6 t) Q3 F- C2 b x
4 P, c; _ }) `# r8 u0 n; ]! J } 9 recvfrom()) V8 Q9 P* f5 {7 ?
头文件:; }* v* o6 s) D7 K: w
#include <sys/types.h>6 p3 q) Q8 r1 h- S0 V
#include <sys/socket.h>" S& |2 X4 V, Y. ?! i* X1 z% e
函数原型:
* x7 X+ S3 p; W$ Z int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)0 u3 g. r W; H9 H, E
+ F3 j9 G$ ^& Y1 d, h8 h# Q" Y 8 j% K0 O% e8 g/ X
10 read() write()
' K1 ^% H4 \, I2 m4 d5 V. S9 g int read(int fd, char *buf, int len)0 G$ K% u( i$ H/ q0 O
int write(int fd, char *buf, int len)3 G2 Y4 P9 z9 T3 v
2 M7 i! [. q/ l- P3 G0 a( l 11 shutdown()
1 f, i) X. l, Y4 W: m- @ close(sockfd)
* G; [& z- c9 V" b2 _# W. z* H int shutdown(int sockfd, int how)0 u, x1 Y- P+ d: K) _
----------------------------------- [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 l" w9 p" Z7 E<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
, q" `+ q' q5 `9 Q0 c1 M<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
) p; X3 K) l i5 g: x<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等
1 d* L1 Z6 q8 q8 |4 l3 ?/ G<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等0 g3 g0 l/ l3 U, V* J
<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等, M2 X7 u7 P+ o0 o' W1 `
<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件! ]0 F- }$ F+ n3 ]" u/ y |! W( Z
" P( J3 ?8 ]+ g$ c5 B: q# F( o[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等7 m( f9 t% H4 G+ W; {! L
#include <sys/types.h>
/ s! y1 y# ^. e0 l5 H0 J2 K1 j, J* T/ n1 g* F9 z: _3 _
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
" H2 e/ p% _5 Y, C* \+ F7 B#include <poll.h> //poll,pollfd
: y0 n u q, ^: o#include <arpa/inet.h> //inet_addr,inet_aton
9 a8 e8 M _% f) w* p) a+ O- b#include <unistd.h> //read,write9 T ~8 K- o8 T9 f: ?/ c N
#include <netdb.h> //gethostbyname
' u) g; s5 J7 t+ k- @; ^% I- o8 @2 Y# x, w6 u# z$ ~
#include <error.h> //perror2 S- p _$ e, [, I7 `$ c
#include <stdio.h>
: k! Y- o1 _$ B' V! A6 n#include <errno.h> //errno7 o- J* p% t! H) n- u' {
% o Q! I) `2 w# J2 r& Z& Q
#include <string.h> // memset' `4 _7 s3 x7 E- i
#include <string>
( s& P" `+ [1 f. P5 w+ b- J#include <iostream>
+ d5 W- A0 U" Y
% D+ {" b4 J$ O; z& { |