|
[size=13.3333px]一 三种类型的套接字:6 P' J: } k A0 k0 _% Y" K7 j
1.流式套接字(SOCKET_STREAM)
/ V% l, a: S( e0 L% x+ a- V 提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
* h& S, X2 d" B6 U+ W# c# k' }- h2.数据报式套接字(SOCKET_DGRAM)
6 `2 A; n3 w5 y& W; @. @: D 提供无连接的数据传输服务,不保证可靠性。
; [- g( d; f1 M3.原始式套接字(SOCKET_RAW)
* {7 I, p4 E# Z' ~ 该接口允许对较低层次协议,如IP,ICMP直接访问。9 n3 s- n N: ]8 x) Q
6 K4 B5 J r& S9 u6 d1 }, W% Z; Y
二 基本套接字系统调有有如下一些:
# V) d9 F- c8 ?; l; x 创建套接字: socket()
G7 E! x ^7 m6 @ 绑定本机端口: bind()
6 d8 Q0 o, Z" O6 i } 建立连接: connect(),accept()) O- E9 i6 H1 `6 p8 [6 f% [- {
侦听端口: listen()* g0 A; B3 ^" A/ P# G3 Z# U
数据传输: send(), recv()3 B, a( U7 M& E( ]- H
输入/输出多路复用: select()
3 P. [5 Y% M g% u) i% y) T+ ] 关闭套接只: closesocket()+ C" R4 N/ R( i) H' {& I/ J
( [( G, U9 p+ ~6 t6 G, }
三 数据类型5 g) M6 I# v6 s" l) g- F
struct sockaddr. {2 g% Q5 m9 n6 ]% `& f" H# \; r
{
3 N z. Z! g0 l9 j, K, U1 @ unsigned short sa_family; //地址族, 一般为AF_INET8 t' M8 K; O! c+ h" _
char sa_data[14]; //14字节的协议地址5 ]% f& n8 P: r, x, U
}
& w! Z, W! {& y& |- F% _8 Y- \
1 W3 Y* ~: @ [, Q7 p struct sockaddr_in* w5 K, k; ]* L* [2 A/ M
{
7 [! ~; @1 i- D" c* ^ short int sin_family; //地址族
& _. w1 A- Z5 K3 w unsigned short int sin_port; //端口号
5 M. ~- \9 ~+ L* z( Q struct in_addr in_addr; //ip地址
- A' R3 n! U! G$ ` unsigned char sin_zero[8]; //填充
& @. J9 Y4 O X }
% Q, F% u. T% }3 r6 B) N; F. b: X- a
$ e5 w5 a9 x6 ?4 d( ^, Q% `四 常用函数
3 \) |5 D- P: ^: b! J 1 socket()
; h5 P; \! S0 j; I 头文件:
% m! `. r8 m- S7 k( i #include <sys/types.h>
& y, o: ?6 d Y4 H8 s# N2 k #include <sys/socket.h># {/ e# K3 P8 b2 _
函数原型:1 p: _) J* U+ o
int socket(int domain, int type, int protocol)
. r, Q1 k1 R' {$ g domain: 协议类型,一般为AF_INET
1 u2 z0 A8 Q; S+ {( n# F type: socket类型
2 a/ [& G+ C* ]% g protocol:用来指定socket所使用的传输协议编号,通常设为0即可
: M4 o5 b' L7 ]6 F# s7 L( D6 ~$ [" \
2 bind()
. u" f9 h- \, n9 i) b. i 头文件:0 P( V) {' K* c1 E8 ?0 O
#include <sys/types.h>
2 L) L) |/ E7 D4 e9 b9 R #include <sys/socket.h>
: |6 J* y: i* o. X 函数原型:5 x4 g8 f0 R. O0 O( U
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)) @4 O1 e3 s# _( x
sockfd: socket描述符& A# k; n% t- V5 v+ H" g' z
my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
6 U/ Z% f( V( |3 I, ~ addrlen:常被设为sizeof(struct sockaddr)
, }+ }+ Q) }5 G3 m" D& _9 U
; c# _$ ~! J" a+ v( D$ [ 3 connect()7 b6 y7 ?% X0 P4 l' T& @
头文件:2 Z9 _/ a1 B& X) ~# \* f
#include <sys/types.h>
4 r* e8 |( d3 F- b* B( c #include <sys/socket.h>
, F! H$ N# D( I- H, { 函数原型:/ [( `0 L1 c" ^7 t$ C
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
9 W. e! j& ?& ?3 f% e& D sockfd: 目的服务器的socket描述符
9 L7 D/ }# |, J; w5 n5 {# d, ~" c serv_addr:包含目的机器ip地址和端口号的指针" T3 D9 O! e0 g1 A
addrlen:sizeof(struct sockaddr)
, u4 Q* N) f! k7 s2 O6 e9 V8 }
0 y7 U( a) q9 N9 U8 `) w8 W 4 listen()
( E# X$ }1 E& D 头文件:+ {2 H- B8 h! ^4 v/ K+ \
#include <sys/socket.h># w5 A& s/ t2 e7 m
函数原型:
3 X, ~! H/ j a/ J( j; f int listen(int sockfd, int backlog);
5 S9 T7 ~* ^( g, g% |7 s sockfd:socket()系统调用返回的socket描述符
2 l& t0 R) B- y, ]: i backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。- e$ _# d3 h5 m& o. J5 Z
* o, j3 g% o |9 |2 j) k' p
5 accept()
8 e( w3 D; p9 _) T 头文件: 1 _ ]& b# Y! V$ K
#include <sys/types.h>9 P0 I5 U- Z) q8 S* F& y5 v6 I
#inlcude <sys/socket.h>
- r2 z5 _( B0 @( {( w: Q 函数原型:
; Y9 B9 }7 U, X/ m9 B w7 \) { int accept(int sockfd, void *addr, int addrlen)
1 }- u1 Z# L1 l; k$ P sockfd:是被监听的socket描述符# t. D5 b) [5 L* E/ ^8 U
addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息) R) i/ V# T: U
addrlen:sizeof(struct sockaddr_in)! W. h: Y1 I& [1 K$ J( d0 z
* a, _6 `5 [9 X$ d5 | 6 send(): ]. q H( {" I1 e& i3 i
头文件:4 I' P1 c Q* Z# Z
#include <sys/socket.h>; D# I1 K+ @- r2 V7 M
函数原型:
+ J- i5 t0 H8 T+ y9 b! { int send(int sockfd, const void *msg, int len, int flags);
* z4 Q$ e$ x) z' | sockfd:用来传输数据的socket描述符/ {/ ^8 C% [0 d" H
msg:要发送数据的指针 * J- T7 ?0 j3 `, [2 m1 r
flags: 0
5 z; G- E5 O% }& M* G ' t, C! N0 ^* h0 k- B; V, Q8 A' \
7 recv(); Q' t& S; j' v
头文件:: Q2 c' ^8 L9 y( x- L: ?& L0 A! B! o* X
#include <sys/types.h>8 B. ~/ P8 S* P2 g
#include <sys/socket.h>
6 }: Z5 _$ e3 _2 ~, v$ N5 O 函数原型:7 C9 @( z3 _/ D+ s& Q& T% m
int recv(int sockfd, void *buf, int len, unsigned int flags)! X: ?: O9 v8 Y- u {. j8 k6 y
sockfd:接收数据的socket描述符8 ]9 |1 Q! H: D8 N) |( ]0 m- Y L
buf:存放数据的缓冲区1 O$ G7 S1 d- F$ o* R3 I7 i3 s6 s
len:缓冲的长度6 N. J9 R# H- B* j
flags:0
( G0 q3 J% Z6 u. x9 h' {- @; V! Y, V* {0 A& b
8 sendto()# T) J! w5 I/ Y& d9 O' N5 Q( L
头文件:
5 j" |2 M) ]" U2 w #include <sys/types.h>$ z$ h$ v8 U4 h8 ~
#include <sys/socket.h>7 ~" D1 q! Y2 ?& w$ S: i) m
函数原型:
! [7 ]* a" D" l+ } int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);8 {: Y5 @. b4 O$ ~1 _
# ?% A. {% U* [7 z
?! T9 d" l' N" e 9 recvfrom()1 y, U$ \4 L0 s t( _8 T
头文件:
$ `' A/ C0 I, s #include <sys/types.h> U# s/ l& Z$ U1 [$ x; s3 o# R- u
#include <sys/socket.h>
3 Z: O4 k3 [/ |9 b# V 函数原型:
( I# [6 H8 {7 D3 a int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)
* [8 q- l+ Y4 ^! ?5 s5 X s& j( V! d
& V4 N P* K' {
4 t& b6 [5 A4 P5 v/ _ 10 read() write()* b0 W6 G" `" N" S/ G
int read(int fd, char *buf, int len)/ O; J6 _9 B. q$ e1 x0 j
int write(int fd, char *buf, int len)% M b( L. r3 y6 v4 e) [# s- U, T
& g: F( v8 V( J7 \1 W1 _ 11 shutdown()6 L* ]. P i+ H8 d! k Q
close(sockfd)) \; l5 e/ w3 e
int shutdown(int sockfd, int how)) c: X' ^% I- b, h
----------------------------------- [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等) ' o) t# O. D5 p
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等% f# L+ E/ O! }$ N6 r2 Z) w% g
<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
! H9 x$ K: }4 J0 ~% }& ]# {<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等$ K. ~. x& J: x( w1 P
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
# Y0 y: `( A7 A/ ~# L, s+ l<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
8 `, @ F$ |9 Q5 ~& S+ A<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件
) O, |+ o2 U: d! j) _9 E8 y8 R. ^, @
[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等# `% I5 B4 b _; d; X/ E
#include <sys/types.h>
t& c" |, ~1 t% V7 c& z
5 o( K8 U' \! W+ z( h7 r1 O. |#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons2 g1 P7 a$ U9 u! l' d/ i
#include <poll.h> //poll,pollfd
3 e0 T1 [ i; M$ y) d# @- O$ P#include <arpa/inet.h> //inet_addr,inet_aton
, H+ K$ v6 w7 |% R7 \' U" G#include <unistd.h> //read,write) c" l4 s/ R9 h" f) R! {1 `5 m
#include <netdb.h> //gethostbyname
. l6 E; t( ?5 Q" L) T2 Q. V: z, f9 U
#include <error.h> //perror T( Z0 ? }1 k2 V4 E
#include <stdio.h>$ ]; H- [2 |* t* D) n0 m
#include <errno.h> //errno: h0 [# Y [' I* Z
, C% k5 Z1 f# N
#include <string.h> // memset
. V! L( H ?' {' k#include <string>
% _1 m% j5 g) R" O9 [4 D#include <iostream>
( V) n* W& X# M: ]7 w9 R
g; `' s- g! A4 r" ` |