如何写一个完美的socket多线程通信程序 ?(持续更新中...)
来源:互联网 发布:程序员专用桌面壁纸 编辑:程序博客网 时间:2024/06/06 02:51
/*
* 由socket多线程通信中一些常见问题与技巧引发的一系列程序开发秘籍,(个人经验,仅供参考)
* 请结合http://blog.csdn.net/ipromiseu/archive/2009/05/12/4169589.aspx《Linux系统下的多线程编程全面入门 》阅读本文
* by . Gray Luo(guohui.great@gmail.com)
*/
1.socket多线程通信中一些常见问题与技巧:
1>socket考虑到效率,一般采用nonblock方式。
2>socket通信或者其它读写操作,使用select进行可读写的检测,一方面可以防止阻塞占用CPU,另一方面可以安全地进行数据读写。
3>read/write 或 recv/send 操作之前都需要使用FD_ISSET()检测句柄是否可读写。
4>read/write 或 recv/send 都需要重新封装以达到对数据的完整收发与出错处理。 请参考我的另一篇文章《通信中如何一次性完整地接收数据》http://blog.csdn.net/ipromiseu/archive/2010/01/05/5138760.aspx
5>对出错的socket,如果无法恢复,则需要销毁,而不能继续进行读写。
6>一个多次循环的操作内,如while(),for()之中的表达式,一定要在每次循环后加上usleep()让出CPU,usleep的长短需要调节以适应程序的各个模块的效率。在这种无限循环中,循环条件需要是一个变量,可不能写成while(1),for(;;)之类的,因为如果写成这样,那当程序出现异常时,可能程序就无法正常退出,对程序资源造成混乱。
7>socket的listen位置,来一个新的连接,就开一个新的线程去处理,这里的线程ID也需要新的ID。这里容易出现bug.
8>socket通信中不能严格按照收发顺序来进行收发数据,即一个socket的通信流程要简洁,彼此之间不能有太多的依赖性。
9>收发数据需要有magic_num/checksum,对于视频音频流可能还需要sequence num,收到header后首先需要判断magic_num/checksum是否正确,
以确定这个packet是否合法。如果不合法,就以max_buff的大小来收,由于是nonblock,所以以最大的包来收,没数据会立即返回,
然后continue. 对于sequence num discontiguous packets,do some process.
如:
10>严格判断函数的返回值,以确定下一步的操作。
11>如果程序出现问题,需要从最开始的源头寻找问题的来源,而不要盲目的脚痛医脚。
12> 使用signal(SIGPIPE, SIG_IGN); 忽略掉socket中断产生的SIGPIPE信号,以致于程序不被异常中断。
13>在write/send的时候,也需要先FD_ISSET() -> rc = read()/recv -> if(rc == 0)则说明收到FIN/RST,socket中断,无法恢复,做清理工作 。
if(rc < 0)且EAGAIN == errno,则socket出错,无法恢复,做清理工作。如 <19>实例所示.
14>适当设置线程的优先级,以达到最重要的线程可以顺畅运行,而不至于时常被打断。
15>不要出现无退出条件的while(1),for(;;)之类的,因为任何一个程序,都有可能被中断,
一旦收到中断信号,线程就需要一个退出条件,while(!flag),当收到某个中断信号后,就需要执行某个函数,在这个函数中做一些清理工作,包括flag = 1;
如:
16>在使用signal(SIGPIPE, SIG_IGN);后程序还是会收到Interrupted system call信号,所以在select处,需要catch这个信号,然后做完一些清理工作再退出。
如下:
17>尽量使函数的功能简单,一个函数只干一件事,对于功能类似的操作,尽量封装到同一函数中。
18>在写socket操作前,先判断该socket是否可读,以确认该socket是否已被关闭。
19>我自己一般读socket方法如下:
eg:
20>函数的返回值,如果定义为unsigned 类型的,对这个函数的返回值判断一定要谨慎,不能以 <0 或者 >0为比较条件,因为它是unsigned,必然大于0。
如:
21> 尽量少用malloc,因为一旦使用了malloc,就注定着你要为它安排一个同伴free(),而有时候你收到了malloc的“好处”就忘记了给它安排完整的free(),
程序任何一个走向都将要给它安排同伴,你逃是逃不掉的。
一旦使用了malloc,也注定了你必然要判断一下它是否是活的,谁都不愿意为死人效劳,因为死人无法给自己带来好处。
eg:
22>当一个listen主进程或者主线程得到一个连接就开一个线程处理时,这个新开的线程中的while循环条件与前面的线程ID一样,
都需要是这个线程独有的,不会影响到其它并发线程,否则,所有线程都将会因为一个线程的坏掉而都死掉。
23>write/recv之前,对方socket中断,write/recv会先调用SIGPIPE响应函数,由于将SIGPIPE交给了系统,则write/recv会返回-1,errno号为EPIPE(32).
- 如何写一个完美的socket多线程通信程序 ?(持续更新中...)
- 自写webrtc程序中遇到的问题---------------------持续更新----------
- 写的一个socket程序
- 一个简单的socket通信聊天程序
- 一个简单的java socket通信程序
- 一个简单的NIO Socket通信程序
- 写一个完美数程序
- java多线程SOCKET程序的一个问题
- 如何写出正确CUDA程序(持续更新中)
- 自己写的一个同步SOCKET通信类 相当实用
- 如何使用boost.asio写一个简单的通信程序(一)
- 非阻塞socket对应的多线程服务器的实现---一个服务器如何与多个客户端进行通信?
- 请教如何改善C#中socket通信机客户端程序的健壮性
- 请教如何改善C#中socket通信机客户端程序的健壮性_C#教程
- 请教如何改善C#中socket通信机客户端程序的健壮性_C#教程
- 用Python写的一个多线程TCP通信实例
- 小的c程序解释,持续更新中.......................
- 一个简单的客户-服务器的Socket通信程序
- dbus实例讲解(二下):消息和消息总线
- 第三章后续翻译【完结】
- 采访Java Collection的作者Joshua Bloch
- 日记0916
- c#读写xml文件
- 如何写一个完美的socket多线程通信程序 ?(持续更新中...)
- Solaris 10 安装 JDK1.6
- DHCP一般配置
- 我的词法分析器
- 密码管理专家代码
- 引用 C#获取当前路径
- jsp笔记之 读取web.xml配置参数
- 复杂事件处理之持续查询语言(continuous query language)
- C#拷贝文件夹及文件