linux服务器编程 ---资料收集:

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wowocpp/article/details/85248993

linux高性能服务器编程+源码(带书签) 31.8M
https://download.csdn.net/download/qq_20772811/10683128

问题

socket服务器开发中的SO_REUSEADDR选项与让人心烦的TIME_WAIT

https://www.cnblogs.com/qiaoconglovelife/p/5416715.html
回想一下,Linux下的TIME_WAIT大概是2分钟,这样也合情合理。那么没有释放掉的资源是什么呢,是端口吗?机智的我立刻决定做实验找出答案。启动服务器程序,在与客户建立连接之后,kill掉服务器。飞快地在terminal里输入命令:netstat -an|grep 9877。这里9877是我服务器打算绑定的端口。果然:
  结果显示9877端口正在被使用,并处于TCP中的TIME_WAIT状态。再过两分钟,我再执行命令netstat -an|grep 9877,世界清静了,什么都没有。

终于找到了答案:果然是TIME_WAIT在捣鬼。

我遇到的情况正好符合情况1,并且书上说了:“所有TCP服务器都应该指定本套接字选项,以允许服务器在这种情形下被重新启动。”那么试试看喽。

UNIX Network Programming

一个很特别的TCP选项TCP_DEFER_ACCEPT

经过测试发现,设置TCP_DEFER_ACCEPT选项后,服务器受到一个CONNECT请求后,操作系统不会Accept,也不会创建IO句柄。操作系统应该在若干秒,(但肯定远远大于上面设置的1s) 后,会释放相关的链接。但没有同时关闭相应的端口,所以客户端会一直以为处于链接状态。如果Connect后面马上有后续的发送数据,那么服务器会调用Accept接收这个链接端口。

感觉了一下,这个端口设置对于CONNECT链接上来而又什么都不干的攻击方式处理很有效。我们原来的代码都是先允许链接,然后再进行超时处理,比他这个有点Out了。不过这个选项可能会导致定位某些问题麻烦。

里面 val 的单位是秒,注意如果打开这个功能,kernel 在 val 秒之内还没有收到数据,不会继续唤醒进程,而是直接丢弃连接。

将sin_addr设置为INADDR_ANY"的含义是什么?

INADDR_ANY
转换过来就是0.0.0.0,泛指本机的意思,也就是表示本机的所有IP,因为有些机子不止一块网卡,多网卡的情况下,这个就表示所有网卡ip地址的意思。
比如一台电脑有3块网卡,分别连接三个网络,那么这台电脑就有3个ip地址了,如果某个应用程序需要监听某个端口,那他要监听哪个网卡地址的端口呢?

如果绑定某个具体的ip地址,你只能监听你所设置的ip地址所在的网卡的端口,其它两块网卡无法监听端口,如果我需要三个网卡都监听,那就需要绑定3个ip,也就等于需要管理3个套接字进行数据交换,这样岂不是很繁琐?

所以出现INADDR_ANY,你只需绑定INADDR_ANY,管理一个套接字就行,不管数据是从哪个网卡过来的,只要是绑定的端口号过来的数据,都可以接收到。

epoll:EPOLLLT和EPOLLET的区别

概念:

Level-triggered :水平触发,缺省模式

edge-triggered :边缘触发

比如redis用LT模式,nginx用ET模式

通知模式:

LT模式时,事件就绪时,假设对事件没做处理,内核会反复通知事件就绪

ET模式时,事件就绪时,假设对事件没做处理,内核不会反复通知事件就绪

事件通知的细节:

1.调用epoll_ctl,ADD或者MOD事件EPOLLIN

LT:如果此时缓存区没有可读数据,则epoll_wait不会返回EPOLLIN,如果此时缓冲区有可读数据,则epoll_wait会持续返回EPOLLIN

ET:如果此时缓存区没有可读数据,则epoll_wait不会返回EPOLLIN,如果此时缓冲区有可读数据,则epoll_wait会返回一次EPOLLIN

2.调用epoll_ctl,ADD或者MOD事件EPOLLOUT

LT:如果不调用epoll_ctl将EPOLLOUT修改为EPOLLIN,则epoll_wait会持续返回EPOLLOUT(前提条件是写缓冲区未满)

ET:epoll_wait只会返回一次EPOLLOUT

针对TCP的测试详请,都是non-blocking:

1.listenfd设置为LT

表现:当3次握手完成,如果不进行accept操作,那么内核会反复通知

2.listenfd设置为ET

https://blog.csdn.net/daiyudong2020/article/details/50439029

epoll

https://blog.csdn.net/ljx0305/article/details/4065058

linux 下epoll与线程池结合使用的简单实例
https://blog.csdn.net/xilango/article/details/52824486

linux中send函数MSG_NOSIGNAL异常消息

最近2周在做 ineedle 的国舜项目扩展,需要使用 socket 的 tcp 连接向对方发送消息,当然需求很简单,只是按照对方要求发送指定格式的消息,程序结构也非常的简单,一对多的 client/server 模型,ineedle 发送给多个服务器消息。我们这边在分析出结果,封装为相应格式消息后发送给对方,只需要在线程循环发送消息即可,便在测试环境中编写简单的socket进行模拟消息发送,一对一发送,能够正常发送消息。可以遇到了一个棘手的问题:在服务器端用ctrl+c 来结束服务器接收进程来模拟服务器宕机的情况,结束服务 socket 进程之后,服务端自然关闭进程,可是 client 端也竟然出乎意料的关闭掉。

这就奇怪了,我在服务端关闭进程,服务器会关闭 tcp 连接,向 client 发送FIN包,client 响应 ack 后,等双向 tcp 连接关闭后,tcp 连接彻底关闭,在 client 端发送消息会失败,返回错误信息,错误消息会被正常的打印出来,可是很多时候错误信息都没有打印( write 函数没有返回),有时候返回了错误信息,但是 client 端进程仍然无辜死掉,我的 client 端可是用的 while(1) 死循环啊,怎么可能。于是乎百度了一番,说法千奇百怪,有说防火墙的问题,关闭防火墙仍然如此。郁闷 ing,测试了其它方法都不行,打印出错误错误码,也没有查询到结果。

最后问了下我们的张总,问题刚给他说完,他便说他以前也遇到这个问题,给我找到了他以前的解决方案。解决方法是使用 send 函数时候在最后一个参数上加 MSG_NOSIGNAL 标记即可。于是自己更改发送函数 write 为 send 并添加 MSG_NOSIGNAL 标志,重新编译,运行,中断 server,果然这个问题被很潇洒的解决了,感谢张总的英明神武。

参考一个博文的介绍

Linux 下当连接断开,还发送数据的时候,不仅 send() 的返回值会有反映,而且还会向系统发送一个异常消息,如果不作处理,系统会出 BrokePipe,程序会退出,这对于服务器提供稳定的服务将造成巨大的灾难。为此,send() 函数的最后一个参数可以设置为 MSG_NOSIGNAL,禁止 send() 函数向系统发送常消息。

《windows网络编程》
<<windows網絡編程>>和<windows 网络编程技术> 是同一本书吗

题名/著者: Windows 网络编程/ (美)Athony Jones,(美)Jim Ohlund著
丛编题名: 微软 .NET 程序员系列
ISBN号: 7-302-05947-0
出版项: 北京 清华大学出版社 2002.10
载体信息: 23cm ⅩⅢ,458页 CNY78.00
附注项: 本书着重于Windows XP中革新的联网特性,同时包含了对C#编程语言的支持。本书还介绍了最新的网际协议:IPv4和IPv6,以及可靠IP多播协议。 读者对象:VB或C++ 的程序开发人员。

猜你喜欢

转载自blog.csdn.net/wowocpp/article/details/85248993