TCP套接字编程模型
来源:互联网 发布:java字符串转日期格式 编辑:程序博客网 时间:2024/05/04 18:27
TCP套接字编程经常使用在客户/服务器编程模型(简称C/S模型)中,C/S模型根据复杂度分为简单的客户/服务器模型和复杂的客户/服务器模型。C/S简单客户/服务器模型是一对一关系,一个服务器端某一时间段内只对应处理一个客户端的请求,迭代服务器模型属于此模型。C/S复杂服务器模型是一对多关系,一个服务器端某一时间段内对应处理多个客户端的请求,并发服务器模型属于此模型。迭代服务器模型和并发服务器模型是socket编程中最常见使用的两种编程模型,图18-5画出两种模型服务端的处理流程。
18-5 迭代服务器&并发服务器图
1. TCP套接字编程模型图
图18-6是TCP套接字编程模型图,画出了客户端与服务端的编程模型和流程。此模型不仅适合迭代服务器,也适合并发服务器,两者实现流程类似,只不过并发服务器接收客户请求(accept)后会fork子进程,由子进程处理客户端的请求。
图18-6 TCP套接字编程模型图
2. TCP编程流程说明
(1) 服务器端编程流程
TCP服务器端编程流程如下:
① 创建套接字;
② 绑定套接字;
③ 设置套接字为监听模式,进入被动接受连接状态;
④ 接受请求,建立连接;
⑤ 读写数据;
⑥ 终止连接。
(2) TCP客户端编程流程
TCP客户端编程流程如下:
① 创建套接字;
② 与远程服务器建立连接;
③ 读写数据;
④ 终止连接。
(3) TCP服务器三种异常情况
TCP服务器有三种异常情况,分别为服务器主机崩溃、服务器主机崩溃后重启、服务器主机关机。
在服务器主机崩溃的情况下,已有的网络连接上发不出任何东西。此时应用程序发出数据后,会阻塞于套接字的读取回应。由于服务器主机崩溃,此时客户TCP会持续重传数据分节,试图从服务器接收一个ACK,重传12次(源自Berkeley的实现)后,客户TCP最终选择放弃,返回给应用经常一个ETIMEDOUT错误;或者是因为中间路由器判定服务器主机不可达,则返回一个目的地不可达的ICMP消息响应,其错误代码为EHOSTUNREACH或ENETUNREACH。另外说明的是,通过设置套接字选项可以更改TCP持续重传等待的超时时间。
在服务器主机崩溃后重启的情况下,如果客户在主机崩溃重启前不主动发送数据,那么客户是不会知道服务器已崩溃。在服务器重启后,客户向服务器发送一个数据分节;由于服务器重启后丢失了以前的连接信息(尽管在服务端口上有进程监听,但连接套接字所在的端口无进程等待),因此导致服务器主机的TCP响应RST;当客户TCP收到RST,向客户返回错误ECONNRESET。如果客户对服务器的崩溃情况很关心,即使客户不主动发送数据也这样,这需要进行相关设置(如设置套接口选项SO_KEEPALIVE或某些客户/服务器心跳函数)。
当服务器主机关机的情况下,由于init进程给所有运行的进程发信号SIGTERM,这时服务器程序可以捕获该信号,并在信号处理程序中正常关闭网络连接。如果服务器程序忽略了SIGTERM信号,则init进程会等待一段固定的时间(通常是5s~20s),然后给所有还在运行的程序发信号SIGKILL。服务器将由信号SIGKILL终止,其终止时,所有打开的描述字被关闭,这导致向客户发送FIN分节,客户收到FIN分节后,能推断出服务器将终止服务。
3. 读写函数的封装
(1)网络数据读写说明
在网络程序中,向套接字文件描述符写时有以下两种可能:
① write的返回值大于0,表示写了部分或者是全部的数据。
② 返回的值小于0,此时写出现了错误,需要根据错误类型来处理。如果错误号为EINTR,则为中断引起,可以忽略进行继续写操作;如果是其他错误号,则表示网络连接出现了问题(可能对方关闭了连接),则需报错退出。
像向套接字文件描述符写数据一样,读也有两种可能:
① read的返回值大于0,表示读了部分或者是全部的数据。
② 返回的值小于0,此时读出现了错误,需要根据错误类型来处理。如果错误号为EINTR,则为中断引起,可以忽略进行继续读操作;如果是其他错误号,则表示网络连接出现了问题,则需报错退出。
(2)读写函数的封装
为了读写函数更加健壮,更加易用,需要对读写函数进行封装。tcpio.c源代码中readn函数对read函数进行了封装,writen函数对write进行了封装。
tcpio.c源代码如下:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
int readn(int fd,void *buffer,int length)
{
int bytes_left;
int bytes_read;
char *ptr;
bytes_left=length;
ptr=buffer ;
while(bytes_left>0)
{
bytes_read=read(fd,ptr,bytes_left);
if(bytes_read<0)
{
if(errno==EINTR)
bytes_read=0;
else
return(-1);
}
else if(bytes_read==0)
break;
bytes_left-=bytes_read;
ptr+=bytes_read;
}
return(length-bytes_left);
}
int writen(int fd,void *buffer,int length)
{
int bytes_left;
int written_bytes;
char *ptr;
ptr=buffer;
bytes_left=length;
while(bytes_left>0)
{
written_bytes=write(fd,ptr,bytes_left);
if(written_bytes<0)
{
if(errno==EINTR) /* 错误由中断引起,可以继续写*/
written_bytes=0;
else /*其他错误,报错退出*/
return(-1);
}
bytes_left-=written_bytes;
ptr+=written_bytes;
}
return(0);
}
摘录自《深入浅出Linux工具与编程》
- TCP套接字编程模型
- TCP套接字编程模型
- tcp套接字编程模型
- TCP套接字编程
- TCP套接字编程
- TCP套接字编程
- TCP套接字编程
- TCP套接字编程
- TCP套接字编程
- TCP套接字编程
- TCP套接字编程
- TCP套接字编程
- TCP套接字编程
- TCP套接字编程
- TCP/UDP的套接字网络编程模型
- 基本TCP套接字编程
- Java TCP套接字编程
- 【socket】TCP套接字编程
- C++源代码网站
- PS快捷键应用大全
- orcad里面pspice报 ERROR -- Missing model 错误
- 微软MVC Ajax简单应用
- 微分方程解特殊差分模型
- TCP套接字编程模型
- XP 组件中没有IIS,如何添加IIS组件
- 【Linux设备驱动程序(第三版)】----HelloWorld
- tomcat存放目录报的错误
- Sqlserver if else case when
- 控制台颜色控制函数
- Ext.data.Store
- 搭建Ubuntu下c/c++编译环境
- android中使用startActivityForResult回传数据