TCP简单客户/服务端程序问题总结

本文基于阅读《UNIX网络编程第3版卷1》第五章TCP客户/服务端程序实例,介绍一个简单的TCP回射程序网络的基本流程和所要考虑的各种异常问题。下图是这个程序所要用到的基本套接字函数。

图片.png

套接字函数简介

int socket(int domain, int type, int protocol);

执行网络IO,第一件事使用socket函数,指定期望的通信协议类型。似于open,用来打开一个网络连接,如果成功则返回一个网络文件描述符(int类型),套接字描述符,简称sockfd。

int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

服务端套接字绑定自己的IP地址与端口号,客户端那边如果没有绑定端口号,内核会给它分配一个临时的端口。绑定成功,返回0,失败返回-1,IP地址不指定,内核会为其选择。

int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

TCP客户端通过connect函数与服务端连接,进行通信。它会激发TCP的三路握手过程,仅在连接建立成功或者出错时才会返回。
出错情况:

  • 1, TCP客户端没有收到SYN分节的响应,则返回ETIMEOUT错误。
  • 2,若对应客户端的SYN响应是RST(复位),则表示服务器主机在我们指定的端口上没有进程在等待与之连接,硬错误,会返回ECONNREFUSED错误。(RST错误的几种类型:补充)
  • 3,路由错误,不可达,软错误。destination unreachable
    connect函数会导致套接字状态从CLOSED到SYN_SENT状态,再成功转到ESTABLISHED状态。
int listen(int sockfd, int backlog);

socket函数创建一个套接字时,是一个主动套接字,下一步会使用connect函数,listen函数则将主动套接字转换为被动套接字,等着别人来连接,它导致套接字状态从CLOSED转为LISTEN状态,关于第二个backlog参数,则涉及到监听套接字的两个队列,backlog为两个队列长度之和:

  • 1,未完成连接队列:客户端发过来的SYN到达服务器,存在其中,等待服务器完成对应的三路握手过程。这些套接字处于SYN_RCVD状态。
  • 2,已完成连接队列:每个已完成TCP三路握手协议的客户对应其中一项。


    图片.png

队列中项的转换过程如下:


图片.png
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

accept的第一个参数为服务器的socket描述字,是服务器开始调用socket()函数生成的,称为监听socket描述字;而accept函数返回的是已连接的socket描述字。
一个服务器通常通常仅仅只创建一个监听socket描述字(listen socket),它在该服务器的生命周期内一直存在。
内核为每个由服务器进程接受的客户连接创建了一个已连接socket描述字(connected socket),当服务器完成了对某个客户的服务,相应的已连接socket描述字就被关闭。

int close(int fd);

close一个TCP socket的缺省行为时把该socket标记为以关闭,然后立即返回到调用进程。该描述字不能再由调用进程使用,也就是说不能再作为read或write的第一个参数。
注意:close操作只是使相应socket描述字的引用计数-1,只有当引用计数为0的时候,才会触发TCP客户端向服务器发送终止连接请求。

关于UNIX网络编程第5章回射网络函数考虑问题点说明

一、正常终止过程

1,客户端终止时,会关闭所有打开的描述符,这会导致客户TCP发送一个FIN给服务器,服务器会以ACK响应,这是tcp终止序列的铅笔部分,至此服务器套接字处于CLOSE_WAIT状态,客户端则处于FIN_WAIT2状态。
2,服务器TCP收到FIN是,子进程会通过调研exit来终止,导致tcp连接终止序列的最后两个分节,一个服务端到客户端的FIN和ACK,至此客户端套接字进入TIME_WAIT状态。
3,服务器子进程终止时,会给父进程发一个SIGCHLD的信号,如果父进程没有处理,子进程进入僵死状态。

二、子进程信号处理

1,fork子进程时,必须捕获SIGCHLD信号
2,当捕获信号是,必须被处理中断的系统调用
3,SIGCHLD的信号处理函数必须正确编写,应使用waitpid函数以免留下僵死进程

三、服务器子进程异常终止:

服务器端fork的子进程被杀死时,会想客户端发送一个FIN,然而此时客户端正被阻塞在fgets函数上,等待从终端输入一行文本,此时终端如果输入一行文本,会导致server terminated prematurely错误,服务器端过早终止

四、数据格式问题:

客户端、服务端不同的实现以不同格式存储二进制数。
不同架构C数据类型上有差异
不同实现结构打包方式不一样
解决办法:
把所有的数值数据转换为文本串
显示顶一个所支持的数据类型的二进制格式

五、SIGPIPE信号:返回broken pipe错误,

在网络编程中经常会遇到SIGPIPE信号,默认情况下这个信号会终止整个进程,当然你并不想让进程被SIGPIPE信号杀死。我们不禁会这样思考:
在什么场景下会产生SIGPIPE信号?
要怎样处理SIGPIPE信号?
  SIGPIPE产生的原因是这样的:如果一个 socket 在接收到了 RST packet 之后,程序仍然向这个 socket 写入数据,那么就会产生SIGPIPE信号。
  这种现象是很常见的,譬如说,当 client 连接到 server 之后,这时候 server 准备向 client 发送多条消息,但在发送消息之前,client 进程意外奔溃了,那么接下来 server 在发送多条消息的过程中,就会出现SIGPIPE信号。对 server 来说,为了不被SIGPIPE信号杀死,那就需要忽略SIGPIPE信号。
参考http://senlinzhan.github.io/2017/03/02/sigpipe/

六、服务器崩溃后重启:

客户端发送一个tcp包到服务器,服务器端崩溃,由于没有客户端的连接信息,将会对这个客户端发送一个RST,此时客户端收到RST时,由于客户端阻塞与read调用,将会导致返回ECONNREST错误,因此客户端必须能检测服务器主机端是否崩溃

参考资料:

《UNIX网络编程卷1》第5章
https://www.cnblogs.com/zhangshenghui/p/6095297.html
http://senlinzhan.github.io/2017/03/02/sigpipe/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,383评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,522评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,852评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,621评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,741评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,929评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,076评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,803评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,265评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,582评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,716评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,395评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,039评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,027评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,488评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,612评论 2 350