[size=13.3333px]一 三种类型的套接字:
# [2 B( I6 ]- ?$ Z+ o6 v; t1.流式套接字(SOCKET_STREAM). m, E3 T5 Y' c5 z, L8 p
提供面向连接的可靠的数据传输服务。数据被看作是字节流,无长度限制。例如FTP协议就采用这种。
M S3 N4 G" Q2 _" P2.数据报式套接字(SOCKET_DGRAM)$ G5 o& C$ C7 ~9 i; K t# ?5 m
提供无连接的数据传输服务,不保证可靠性。
. P# ?/ ?3 ^ F _0 g! l3.原始式套接字(SOCKET_RAW)
. D3 [" e/ m/ l* e 该接口允许对较低层次协议,如IP,ICMP直接访问。0 l+ V7 H7 l4 ~; l
7 Y4 G' J0 E* J
二 基本套接字系统调有有如下一些:4 x% {& m8 P8 v
创建套接字: socket()
& ] _% t- ?4 A% v 绑定本机端口: bind()! M1 k3 R( f) N0 b# Z: }
建立连接: connect(),accept(). F6 v/ T' v9 u
侦听端口: listen()
8 m1 \; T8 X. Y- U5 e9 { 数据传输: send(), recv()
; f1 Q2 D& U3 y 输入/输出多路复用: select()
* K' ~; l9 t) e7 I 关闭套接只: closesocket()8 ]) `6 z$ ~. X1 k/ Y5 G! [
4 U. z9 s+ F0 j. V C- P" j) o! x9 i三 数据类型
# g4 S- [2 k5 q- J struct sockaddr
( P' W$ L8 Y- Y7 w6 W4 B0 T' J, e4 m {
6 R. H% @# G, U' e; ` unsigned short sa_family; //地址族, 一般为AF_INET- `! I' m& l- c" E% V
char sa_data[14]; //14字节的协议地址: I# }( M3 P& `$ I1 @% p
}9 t; e7 D0 H3 Z% U5 j) s: ?, i- o* a
1 a/ k- t1 W% Y% R- B' n T
struct sockaddr_in% e( C6 ^3 S5 i6 i, u& N! k. g
{
- a: F9 G1 I' p' g short int sin_family; //地址族
, r* S' t1 l' y4 p, _- M unsigned short int sin_port; //端口号/ C% m* D0 q0 C$ ^2 P5 s _
struct in_addr in_addr; //ip地址, L. S# E: K' U& v8 p: l& u! c
unsigned char sin_zero[8]; //填充+ p" I* }# |- j. V, v; `
}
1 w1 H _- d. A# U# s* z! b8 g
0 H& w# _- U5 N! e z- {( e; n四 常用函数3 B) X9 x) X$ R: b* `- ^$ u3 J
1 socket()
2 d1 S& T# h( k' i. F 头文件: 7 D9 f6 @# ]- |3 y3 R: V* B
#include <sys/types.h>' x( Q" \& z" }" c2 W) T
#include <sys/socket.h>
5 k! L w8 G2 K; [( z 函数原型:
, l0 N: }- ~1 @; d/ ~2 V; [/ L int socket(int domain, int type, int protocol)* g9 _5 N) _7 J [4 t
domain: 协议类型,一般为AF_INET
: O1 w2 ~) n" w# d( R6 { type: socket类型& n# O, @- V2 W# v& i
protocol:用来指定socket所使用的传输协议编号,通常设为0即可0 j( L4 F& ]0 i. `4 s; o% C. i
5 j( E/ v8 @0 |
2 bind()5 c! w. T$ d7 \, v' H3 ^5 l- }
头文件:
3 ~1 Y# |+ Y4 B8 C" ]; g4 U #include <sys/types.h>
% E+ I+ j D+ x' e8 P #include <sys/socket.h>4 |' u/ A+ |0 c! d0 D8 R. N
函数原型:
R* D1 N4 U1 w. u3 T int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
( t+ R' a* ~$ B3 e6 y sockfd: socket描述符
) A/ h- E/ e/ h: l$ I5 k. B7 U& m my_addr:是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针
+ ~/ Y; |, N; J# S addrlen:常被设为sizeof(struct sockaddr)
; g8 f1 k5 ^* j+ \4 O
' o" \7 m) P% V: h8 X( r( v N 3 connect()
1 L/ m: w' t2 e/ G+ l+ l 头文件:
$ j2 i4 `4 j0 z5 I2 y8 @3 Y0 j! ` #include <sys/types.h> 3 d" ?& Z' g+ o( k1 \' K
#include <sys/socket.h>, W0 t+ p- Y8 L- Z0 N
函数原型:
3 U3 z: r8 ]) b1 r3 k int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
) n, I& x! m$ s& z" K8 o% x( R sockfd: 目的服务器的socket描述符
8 ^- U. Z' Q3 t; n serv_addr:包含目的机器ip地址和端口号的指针3 x; X. H3 F! a, Z- p$ Z
addrlen:sizeof(struct sockaddr)- ] l c: D- C' C$ u9 Y0 i
4 u: ^2 j1 S* s7 X' Q% H" }0 t+ k 4 listen()" ?& [; k) L5 O) `' n: h- D
头文件:$ c( v0 U2 _8 }1 I+ r0 D% X! @
#include <sys/socket.h>3 U1 X. A! T& v4 C, K! @
函数原型:1 k+ c+ n. X- a7 b5 s4 b/ D, N3 E A
int listen(int sockfd, int backlog);
1 J* [+ A$ v. D5 R! p0 e9 u sockfd:socket()系统调用返回的socket描述符4 A3 \# g' m. e! J3 q* P1 G
backlog:指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept()它们。- M/ \+ W- l; a- h
q& i3 z9 {8 M6 t
5 accept()
, O/ _1 V9 U& b/ B& z8 F1 k 头文件: 0 j; g" Y" b( h) x# L9 o9 V
#include <sys/types.h>
* X% s2 l3 s. p. q. p: c #inlcude <sys/socket.h>4 U2 }# Q( J0 t |
函数原型:; g' \. R! Y" X1 A, R$ X, q4 ]2 H5 u
int accept(int sockfd, void *addr, int addrlen)4 C- e: K5 ^" C
sockfd:是被监听的socket描述符
# i& O6 s1 T. f* X addr:通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息
& _0 h2 `1 s6 \& ?3 P8 h& Q7 ~, q addrlen:sizeof(struct sockaddr_in)
( x" {7 i$ ?9 j , Q. ?/ c0 R8 K! R4 ~, v3 Z! a. Q$ W
6 send()- @/ G2 ?, F. @, M3 t- J) W, n
头文件:+ ]$ y2 I1 ?4 I- O* ^7 g
#include <sys/socket.h>
# z4 `* Z1 {0 S ?1 Z9 D8 r 函数原型:5 \8 ^% w) r1 w! x% X' X$ @5 M
int send(int sockfd, const void *msg, int len, int flags);
/ N! F! U, U7 Z) Y5 z* Z( h sockfd:用来传输数据的socket描述符- B& U! K- }- F4 V! ?6 S
msg:要发送数据的指针 / \. c9 o# f+ j I
flags: 06 \& a. P6 N& {9 E& |/ H- B3 u& |5 H
# L9 b' @$ S4 p' g 7 recv(); s1 g1 A c7 G; C5 g
头文件:
) U6 o! p! H0 F3 ^( q+ o9 F/ A2 I #include <sys/types.h>4 i8 x! z- k5 U) }, _0 k
#include <sys/socket.h>
. e# @+ {* V+ \+ A: a3 g 函数原型:
+ e5 u! S4 i# x0 Q2 D% t- k) w int recv(int sockfd, void *buf, int len, unsigned int flags)% ~- V% v0 I/ J
sockfd:接收数据的socket描述符
8 l2 k# h) n5 O. i6 x- U0 e buf:存放数据的缓冲区* m4 \5 p: }: ^9 F9 I8 [
len:缓冲的长度! A1 Q6 \' n- T
flags:0
6 }" `9 E4 I9 @4 u( J4 G. P, |6 j' F- Z6 W( c
8 sendto()% ?# ]# }* p8 f$ W4 P9 F
头文件:8 R9 w# R0 g9 o
#include <sys/types.h>
. J; C0 s& _+ W' M& l$ M0 R #include <sys/socket.h>
! c. [1 d1 b+ P- v$ [! n 函数原型:' C7 H; U( e. Q: s5 `! z
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
' e0 W$ w' Y+ p* A, Y
2 L7 K9 R% }3 D) `* Y
; B6 y: K6 K/ d# o, M1 r& C 9 recvfrom()
! ^* {/ t' r/ |! g$ T 头文件:
@8 m' D/ ]9 l# o5 O' R #include <sys/types.h>
' J4 ], H$ p2 N" Q2 C #include <sys/socket.h>7 Z/ C% v- l! i
函数原型:+ }7 z G% x* x9 R/ C
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int fromlen)
/ _6 G% @3 Y% z; d. _+ t: N; y3 Y( w" _: |, ]
5 E4 X. S# h% q 10 read() write(); ]/ c" h! k6 U, _4 N) u
int read(int fd, char *buf, int len)
9 t& [- b6 ^1 ~/ _! [! d' s int write(int fd, char *buf, int len)7 G6 N3 R4 N, F
, ]* E7 i [' ?) R- Q 11 shutdown()
/ S+ x _! m/ ^$ S! s( x8 @4 J close(sockfd)0 V) T* ^% o2 W. u( ]! z
int shutdown(int sockfd, int how)* U9 c7 e6 T' [/ H9 Z# C1 @) y( h1 S
----------------------------------- [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等) 0 a8 x; q3 _0 E% F" L' q
<sys/socket.h> //与套接字相关的函数声明和结构体定义,如socket()、bind()、connect()及struct sockaddr的定义等
3 [/ Z. u7 s% x1 W( j( n% T<sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
1 [$ C/ K2 p6 l7 ?7 G<stdlib.h> //某些结构体定义和宏定义,如EXIT_FAILURE、EXIT_SUCCESS等2 ^0 Q4 I7 A+ {; L( O
<netdb.h> //某些结构体定义、宏定义和函数声明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
# ?9 j8 }4 R# \; q* H: {. Q<arpa/inet.h> //某些函数声明,如inet_ntop()、inet_ntoa()等
4 E, d8 g2 l( P2 f( [<netinet/in.h> //某些结构体声明、宏定义,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等 [size=13.3333px]------------------------------ [size=13.3333px]linux下socket编写常用头文件
# ]+ }! U9 j5 B- i" R
% j( r& V! j2 M' ]" D[size=13.3333px]#include <sys/socket.h> //connect,send,recv,setsockopt等
7 p! |* G- U ~# J/ Z#include <sys/types.h>
! r! V' O" V6 r) h9 a9 h% f1 `9 F4 t% l2 c: `" b
#include <netinet/in.h> // sockaddr_in, "man 7 ip" ,htons
8 m$ P4 l/ D" Y' N#include <poll.h> //poll,pollfd
/ C+ v& S7 ~ |0 `#include <arpa/inet.h> //inet_addr,inet_aton
+ _. P% w9 {; M8 {#include <unistd.h> //read,write- H- |- x' o& n/ f( s
#include <netdb.h> //gethostbyname
6 I- B& v+ E |0 F6 u; K' M& _5 U3 g( A/ C( |6 I
#include <error.h> //perror
8 C* j; M' K; j& @5 k; L+ x#include <stdio.h>
3 J+ x. R$ F* P7 ?7 Y) f. K#include <errno.h> //errno0 m/ p" | v) q5 u. P
) _* ` ^. }) _* J; G#include <string.h> // memset( `( z+ a! G" Z2 a4 U8 u
#include <string>
9 J6 H+ F; N3 h% l7 |6 i. o#include <iostream>' y* p/ O( K2 i% f& ]
9 x6 n1 j9 C. J: f( A
|