CS编程模型
每个网络应用都是基于客户端-服务器模型的。
客户端-服务器模型中的基本操作是事务。一个客户端-服务器事务由以下四步组成:
1.当一个客户端需要服务时,它向服务器发送一个请求,发起一个事务。
2.服务器收到请求后,解释它,并以适当的方式操作它的资源。
3.服务器给客户端发送一个响应,并等待下一个请求。
4.客户端收到响应并处理它
网络
客户端和服务器通常运行在不同的主机上,并通过计算机网络的硬件和软件资源来通信。
对主机而言,网络是一种I/O设备,是数据源和数据接收方
从物理上而言,网络是一个按照地理远近组成的层次系统。最低层是LAN(局域网),最流行的局域网技术是以太网。
套接字接口
套接字接口是一组函数,它们和Unix I/O函数结合起来,用以创建网络应用。
套接字地址结构
从Linux内核看,一个套接字就是通信的一个端点,从Linux程序看,套接字就是一个有相应描述符的打开文件.
因特网的套接字地址存放在sockaddr_in的16字节结构中,对于IPV4来说,sin_family为AF_INET,sin_port为一个16位的端口号,sin_addr为一个32位的IP地址。
socket函数
客户端和服务器使用socket函数来创建一个套接字描述符
#include<sys/types.h>
#include<sys/socket.h>
int socket(int domain,int type,int protocol);//返回:成功返回非负描述符,出错-1
domain:即协议域,又称为协议族(family)。常用的协议族有,AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。
type:指定socket类型。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。
(1)SOCK_STREAM(流套接字) 提供面向连接、可靠的数据传输服务。使用了TCP协议
(2)SOCK_DGRAM(数据报套接字)提供无连接的服务,使用UDP协议
(3)SOCK_RAW(原始套接字) 提供单一的网络访问,这个socket类型使用ICMP公共协议
protocol:故名思意,就是指定协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议
注意:并不是上面的type和protocol可以随意组合的,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当protocol为0时,会自动选择type类型对应的默认协议。
例:对于ipv4创建socket,其中使用tcp协议
sock = socket(AF_INET,SOCK_STREAM,0);
connect函数
客户端通过调用connect函数建立和服务器的连接
#include<sys/socket.h>
int connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen);//返回:成功则为0,出错-1
第一个参数即为客户端的socket描述字
第二参数为服务器的socket地址
第三个参数为socket地址的长度,一般为sizeof(sockaddr_in)。
connect函数回阻塞,一直到连接成功建立或发生错误。
bind函数
bind函数告诉内核将addr中的服务器套接字地址和套接字描述符sockfd联系起来
#include<sys/socket.h>
int bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen);//返回:成功0,出错-1
第一个参数sockfd是由socket()调用返回的套接口文件描述符。
第二个参数addr是指向数据结构sockaddr的指针。数据结构sockaddr中包括了关于你的地址、端口和IP地址的信息。
第三个参数addrlen可以设置成sizeof(struct sockaddr_in)。
listen函数
listen函数将sockfd从一个主动套接字转化为一个监听套接字。
如果作为一个服务器,在调用socket()、bind()之后就会调用listen()来监听这个socket,如果客户端这时调用connect()发出连接请求,服务器端就会接收到这个请求。
#include<sys/socket.h>
int listen(int sockfd,int backlog);//成功0,出错-1
第一个参数即为要监听的socket描述符,第二个参数为相应socket可以排队的最大连接个数。