Linux Socket编程注意事项
Socket API 是网络应用程序开发中实际应用的标准 API。虽然该 API 简单。可是开发新手可能会经历一些常见的问题。本文识别一些最常见的隐患并向您显示怎样避免它们。
隐患 1.忽略返回状态
第一个隐患非常明显,但它是开发新手最easy犯的一个错误。
假设您忽略函数的返回状态,当它们失败或部分成功的时候,您或许会迷失。
反过来。这可能传播错误。使定位问题的源头变得困难。
捕获并检查每个返回状态。而不是忽略它们。考虑清单 1 显示的样例,一个套接字 send 函数。
清单 1. 忽略 API 函数返回状态
int status, sock, mode;
/* Create a new stream (TCP) socket */
sock = socket( AF_INET, SOCK_STREAM, 0 );
...
status = send( sock, buffer, buflen, MSG_DONTWAIT );
if (status == -1) {
/* send failed */
printf( "send failed: %s\n", strerror(errno) );
} else {
/* send succeeded -- or did it? */
}
清单 1 探究一个函数片断,它完毕套接字 send 操作(通过套接字发送数据)。函数的错误状态被捕获并測试,但这个样例忽略了 send 在无堵塞模式(由 MSG_DONTWAIT 标志启用)下的一个特性。
send API 函数有三类可能的返回值:
· 假设数据成功地排到传输队列。则返回 0。
· 假设排队失败。则返回 -1(通过使用 errno 变量能够了解失败的原因)。
· 假设不是全部的字符都可以在函数调用时排队,则终于的返回值是发送的字符数。
因为 send 的 MSG_DONTWAIT 变量的无堵塞性质,函数调用在发送全然部的数据、一些数据或没有发送不论什么数据后返回。在这里忽略返回状态将导致不全然的发送和随后的数据丢失。
隐患 2.对等套接字闭包
UNIX 有趣的一面是您差点儿能够把不论什么东西看成是一个文件。文件本身、文件夹、管道、设备和套接字都被当作文件。
这是新颖的抽象,意味着一整套的 API 能够用在广泛的设备类型上。
考虑 read API 函数,它从文件读取一定数量的字节。
read 函数返回读取的字节数(最高为您指定的最大值);或者 -1,表示错误;或者 0,假设已经到达文件末尾。
假设在一个套接字上完毕一个 read 操作并得到一个为 0 的返回值,这表明远程套接字端的对等层调用了 close API 方法。该指示与文件读取同样 —— 没有多余的数据能够通过描写叙述符读取(參见 清单 2)。
清单 2.适当处理 read API 函数的返回值
int sock, status;
sock = socket( AF_INET, SOCK_STREAM, 0 );
...
status = read( sock, buffer, buflen );
if (status > 0) {
/* Data read from the socket */
} else if (status == -1) {
/* Error, check errno, take action... */
} else if (status == 0) {
/* Peer closed the socket, finish the close */
close( sock );
/* Further processing... */
}
相同,能够用 write API 函数来探測对等套接字的闭包。
在这样的情况下,接收 SIGPIPE 信号,或假设该信号堵塞,write 函数将返回 -1 并设置 errno 为 EPIPE。
隐患 3.地址使用错误(EADDRINUSE)
您能够使用 bind API 函数来绑定一个地址(一个接口和一个port)到一个套接字端点。能够在server设置中使用这个函数,以便限制可能有连接到来的接口。也能够在client设置中使用这个函数,以便限制应当供出去的连接所使用的接口。bind 最常见的使用方法是关联port号和server,并使用通配符地址(INADDR_ANY),它同意不论什么接口为到来的连接所使用。
bind 普遍遭遇的问题是试图绑定一个已经在使用的port。
该陷阱是或许没有活动的套接字存在,但仍然禁止绑定port(bind 返回EADDRINUSE)。它由 TCP 套接字状态 TIME_WAIT 引起。该状态在套接字关闭后约保留 2 到 4 分钟。
在 TIME_WAIT 状态退出之后。套接字被删除,该地址才干被又一次绑定而不出问题。
等待 TIME_WAIT 结束可能是令人恼火的一件事,特别是假设您正在开发一个套接字server,就须要停止server来做一些修改,然后重新启动。幸运的是,有方法能够避开 TIME_WAIT 状态。能够给套接字应用 SO_REUSEADDR 套接字选项,以便port能够立即重用。
考虑清单 3 的样例。在绑定地址之前,我以 SO_REUSEADDR 选项调用 setsockopt。
为了同意地址重用,我设置整型參数(on)为 1 (不然。能够设为 0 来禁止地址重用)。
清单 3.使用 SO_REUSEADDR 套接字选项避免地址使用错误
int sock, ret, on;
struct sockaddr_in servaddr;
/* Create a new stream (TCP) socket */
sock = socket( AF_INET, SOCK_STREAM, 0 ):
/* Enable address reuse */on = 1;
ret = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );
/* Allow connections to port 8080 from any available interface */
memset( &servaddr, 0, sizeof(servaddr) );servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
servaddr.sin_port = htons( 45000 );
/* Bind to the address (interface/port) */
ret = bind( sock, (struct sockaddr *)&servaddr, sizeof(servaddr) );
在应用了 SO_REUSEADDR 选项之后,bind API 函数将同意地址的马上重用。
隐患 4.TCP 中的帧同步假定
TCP 不提供帧同步,这使得它对于面向字节流的协议是完美的。这是 TCP 与 UDP(User Datagram Protocol,用户数据报协议)的一个重要差别。UDP 是面向消息的协议,它保留发送者和接收者之间的消息边界。TCP 是一个面向流的协议,它假定正在通信的数据是无结构的,如图 1 所看到的。
图 1.UDP 的帧同步能力和缺乏帧同步的 TCP
图 1 的上部说明一个 UDP client和server。左边的对等层完毕两个套接字的写操作,每一个 100 字节。
协议栈的 UDP 层追踪写的数量,并确保当右边的接收者通过套接字获取数据时,它以相同数量的字节到达。换句话说。为读者保留了写者提供的消息边界。
如今,看图 1 的底部.它为 TCP 层演示了同样粒度的写操作。两个独立的写操作(每一个 100 字节)写入流套接字。
但在本例中,流套接字的读者得到的是 200 字节。协议栈的 TCP 层聚合了两次写操作。这样的聚合能够发生在 TCP/IP 协议栈的发送者或接收者中不论什么一方。
重要的是,要注意到聚合或许不会发生 —— TCP 仅仅保证数据的有序发送。
对大多数开发者来说,该陷阱会引起困惑。
您想要获得 TCP 的可靠性和 UDP 的帧同步。除非改用其它的传输协议,比方流传输控制协议(STCP),否则就要求应用层开发者来实现缓冲和分段功能。
Linux Socket编程注意事项的更多相关文章
- Linux Socket 编程简介
在 TCP/IP 协议中,"IP地址 + TCP或UDP端口号" 可以唯一标识网络通讯中的一个进程,"IP地址+端口号" 就称为 socket.本文以一个简单的 ...
- Linux socket 编程中存在的五个隐患
前言: Socket API 是网络应用程序开发中实际应用的标准 API.尽管该 API 简单,但是 开发新手可能会经历一些常见的问题.本文识别一些最常见的隐患并向您显示如何避免它 ...
- Linux Socket编程
“一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. ——有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览 ...
- Linux Socket编程(不限Linux)【转】
转自:http://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html “一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几 ...
- Linux Socket编程(不限Linux)
"一切皆Socket!" 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. --有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信 ...
- Socket详解-Linux Socket编程(不限Linux)
“一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. ——有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览 ...
- Windows Socket和Linux Socket编程的区别 ZZ
socket相关程序从Windows移植到Linux下需要注意的: 1)头文件 Windows下winsock.h/winsock2.h Linux下sys/socket.h 错误处理:errno.h ...
- Linux socket编程示例(最简单的TCP和UDP两个例子)
一.socket编程 网络功能是Uinux/Linux的一个重要特点,有着悠久的历史,因此有一个非常固定的编程套路. 基于TCP的网络编程: 基于连接, 在交互过程中, 服务器和客户端要保持连接, 不 ...
- Linux Socket编程-(转自吴秦(Tyler))
"一切皆Socket!" 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. --有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信 ...
随机推荐
- 在MAC系统里添加开机启动任务(但是怎么才能知道自己程序的固定位置呢?)
公司最近购进了几台MAC台式电脑,要在上面为一个项目做测试. MAC这么高大上的东西,还是第一次接触,折腾了半天好不容易安装了一些需要的应用服务上去,跑了一下还不错. 公司提倡节约用电,下班之后要把所 ...
- 通过xml生成word文档
Xml生成word总结 使用xml生成word的基本步骤在<使用xslt转化xml数据形成word文档导出.doc>中说明比较清楚了.但是其中的细节并未说到,因此自己折腾了两天总算成功了. ...
- php Smarty模板引擎配置与测试
Smarty简介 smarty是一个使用PHP写出来的模板PHP模板引擎,它提供了逻辑与外在内容的分离,简单的讲,目的就是要使用PHP程序员同美工分离,使用的程序员改变程序的逻辑内容不会影响到美工的页 ...
- Javascript面向对象研究心得
这段时间正好公司项目须要,须要改动fullcalendar日历插件,有机会深入插件源代码.正好利用这个机会,我也大致学习了下面JS的面向对象编程,感觉收获还是比較多的. 所以写了以下这篇文章希望跟大家 ...
- 管理启示,不起毛的鹦鹉——leo锦书54
下面一个很长的故事后,我真的很期待明确: 一个人去买鹦鹉,看到一仅仅鹦鹉前标:此鹦鹉会两国语言,售价二百元.还有一仅仅鹦鹉前则标道:此鹦鹉会四门语言.售价四百元.该买那仅仅呢?两仅仅都毛色鲜亮, ...
- 用反射,将DataRow行转为Object对象
/// <summary> /// 反射辅助类 /// </summary> public class ReflectionHelper { /// <summary&g ...
- 跟着鬼哥学so改动,一,准备篇
图/文 听鬼哥说故事 闲话少说,so的改动,重要性大家都知道,这里从头编写so文件,分析so文件,改动so文件,打算做一个系列的教程,当然,主要是看时间同意. android的sdk配置以及ndk环境 ...
- Eclipse用法和技巧五:生成说明文档2
上面一篇文章里面我们介绍了一种生成可以被JDK提取到,生成JavaDoc的添加注释方法.下面再补充一种生成这种注释的方法,上图: 步骤一:光标移动到需要添加注释的语句旁边,快捷键:shift + al ...
- 基于visual Studio2013解决C语言竞赛题之1084完全平方数
题目 解决代码及点评 /************************************************************************/ /* ...
- 用python将SQL格式文件改成自己想要的格式
INSERT INTO TTT (NSAME, ID, AGE) VALUES ('AAA', '201023210816', '22'); 将上面的SQL格式改成以下的格式 AAA|20102321 ...