1.必须了解tcp、udp头部的内容结构。

tcp通信

在bind绑定如果指定的ip为INADDR_ANY,意味着可以收到系统所有网卡的数据包。可以调用getsockname来发现绑定到一个套接字的地址。如果套接字已经和对方连接,可调用getpeername获取对方的地址。

ip地址转换函数

除了和windows的一样外,inet_addr()、inet_ntoa()外。

在linux中,inet_aton()也是从字符串转换成4字节网络字节序。

ipv4和ipv6都使用的函数

inet_pton()和inet_ntop()    p:表示表达,即字符串     n:表示数值。

在linux上使用套接字编程引用的头文件是#include<sys/socket.h>

与windows不同的地方

1.关闭使用close函数,而windows使用closesocket

2.接收使用read,而windows使用recv或

3.发送使用write,而windows使用send

在linux环境中,关闭套接字和windows有所不同。

客户端进程终止处理的部分工作就是关闭所有打开的描述符,因此客户打开的套接字由内核关闭。这导致客户tcp发送一个fin给服务器,服务器tcp则以ack响应。这意味着关闭套接字也可以不用显性调用close函数,而是调用关闭进程的函数exit,直接关闭进程即可。

同理,服务端的进程关闭后,也会关闭所有的打开描述符。

信号处理

信号处理函数,异步的

sigfunc *signal(int signo,sigfunc *func)

signo:信号名,如子进程结束后,会发SIGCHILD信号

func:信号处理函数指针

慢系统调用

基本规则:当阻塞于某个慢系统调用的一个进程捕获某个信号且响应信号处理函数返回时,该系统调用可能返回一个EINTR错误。

这就需要实现自己重启被中断的系统调用。

如 if(errno == EINTR)

{

continue;

}

accept、read、write、select、open都适合使用重启。而connect不能再次调用重启,会报错的。

网络编程可能遇到三种情况

1.当fork子进程,必须捕获SIGCHILD信号。  可通过sigfunc *signal(int signo,sigfunc *func)

2.当捕获信号时,必须处理被中断的系统调用。 if(errno == EINTR)   continue;

3.SIGCHILD信号处理函数必须正确编写,应使用waitpid函数避免僵尸进程。

TCP协议RST

一、RST介绍

RST标示复位、用来异常的关闭连接。

1. 发送RST包关闭连接时,不必等缓冲区的包都发出去,直接就丢弃缓冲区中的包,发送RST。

2. 而接收端收到RST包后,也不必发送ACK包来确认。

二、什么时候发送RST包

1.  服务器程序端口未打开而客户端来连接. 具体表现为客户端建立连接的SYN到达服务器某端口,但是该端口上没有正在 监听的服务。

2. 请求超时。 使用setsockopt的SO_RCVTIMEO选项设置recv的超时时间。接收数据超时时,会发送RST包。

3.提前关闭,如服务端提前关闭。

4.在一个已关闭的socket上收到数据。其实和第3条应该差不多的。

三、尝试手动发送RST包

1. 使用shutdown、close关闭套接字,发送的是FIN,不是RST。

2. 套接字关闭前,使用sleep。对运行的程序Ctrl+C,会发送FIN,不是RST。

3. 套接字关闭前,执行return、exit(0)、exit(1),会发送FIN、不是RST。

以上几种方法,都不能发送RST包。 发送RST包,需要自己伪造数据包进行发送。

SIGPIPE信号,  需要重温信号这章节

当服务器close一个连接时,若client端接着发数据。根据TCP协议的规定,会收到一个RST响应,client再往这个服务器发送数据时,系统会发出一个SIGPIPE信号给进程,告诉进程这个连接已经断开了,不要再写了。

又或者当一个进程向某个已经收到RST的socket执行写操作是,内核向该进程发送一个SIGPIPE信号。该信号的缺省学位是终止进程,因此进程必须捕获它以免不情愿的被终止。

根据信号的默认处理规则SIGPIPE信号的默认执行动作是terminate(终止、退出),所以client会退出。若不想客户端退出可以把 SIGPIPE设为SIG_IGN

如:signal(SIGPIPE, SIG_IGN);
这时SIGPIPE交给了系统处理。

服务器采用了fork的话,要收集垃圾进程,防止僵尸进程的产生,可以这样处理:
signal(SIGCHLD,SIG_IGN);
交给系统init去回收。
这里子进程就不会产生僵尸进程了。

如果服务器一直崩溃,客户端tcp持续重传数据,试图从服务器得到一个ack。在一定时间后,服务器会给客户端返回一个错误ETIMEDOUT.

如果某个中间路由器判断服务器主机不可达(如可以断开网络),返回错误是EHOSTUNREACH或ENETUNREACH。

ECONNRESET是linux环境网络编程产生的错误,出现该情况原因有:

服务器端重启连接,还未建立连接 。客户端调用read函数会出现该错误值。

服务器关机,init进程给所有进程发送SIGTERM信号(可捕获),等待一段时间(5-20s),然后给所有扔运行的进程发送SIGKILL信号(不可捕获)。

阻塞式io模型、非阻塞式io模型、io复用模型、信号驱动式io模型都是同步io模型,因为真正的io操作将阻塞进程。

只有异步io模型才是异步的。

select

int select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)

nfds:所传入的最大文件描述符+1。所有加入集合的句柄值的最大那个那个值还要加1

readfds、writefds、exceptset:分别指向可读、可写和异常等事件对应的描述符集合。不感兴趣,则设置为null.

timeout: 用于设置select函数的超时时间,即告诉内核select等待多长时间之后就放弃等待。timeout == NULL 表示等待无限长的时间.

返回值分为三种情况:

  1. 做好准备的文件描述符的个数
  2. 返回0:超时;
  3. 返回-1:错误;

writefds包括符合以下任一个条件的套接字:

1.有数据可以发出

2.如果一个非阻塞connect连接请求正在被处理,并且连接已经成功  。或者connect已经已失败告终

3.该连接的写半部关闭。在linux系统,这样的套接字写操作会产生SIGPIPE信号。

4.有一个套接字错误待处理。

readfds包括符合以下人一个条件的套接字:

1.有数据可以读入

2.连接已经被关闭、重启或终止。

如果是关闭,套接字可读,会接收到fin,并read返回0.

如果是服务器崩溃并重启的话,套接字可读,会收到rst,并read返回-1。

3.假如已调用了listen,而且已完成的连接数不为0.

poll

#include <poll.h>

int poll(struct pollfd fds[], nfds_t nfds, int timeout);

struct pollfd {

int fd; /*文件描述符*/

short events; /* 等待的需要测试事件 */

short revents; /* 实际发生了的事件,也就是返回结果 */

};

events及revents的常量如下

常量

说明

POLLIN

普通或优先级带数据可读

POLLRDNORM

普通数据可读

POLLRDBAND

优先级带数据可读

POLLPRI

高优先级数据可读

POLLOUT

普通数据可写

POLLWRNORM

普通数据可写

POLLWRBAND

优先级带数据可写

POLLERR

发生错误

POLLHUP

发生挂起

POLLNVAL

描述字不是一个打开的文件

nfds:nfds_t类型的参数,用于标记数组fds中的结构体元素的总数量;

timeout:是poll函数调用阻塞的时间,单位:毫秒;    INTTIM 永远等待

返回值

>0:数组fds中准备好读、写或出错状态的那些socket描述符的总数量;

==0:数组fds中没有任何socket描述符准备好读、写,或出错;此时poll超时,超时时间是timeout毫秒

-1: poll函数调用失败,同时会自动设置全局变量errno;

#include <sys/socket.h>

int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t*optlen);

int setsockopt(int sockfd, int level, int optname, void *optval, socklen_t*optlen);

sockfd:一个标识套接口的描述字。

level:选项定义的层次。例如,支持的层次有SOL_SOCKET、IPPROTO_TCP。

optname:需获取的套接口选项。

optval:指针,指向存放所获得选项值的缓冲区。

optlen:指针,指向optval缓冲区的长度值。

SO_KEEPALIVE选项

SO_LINGER选项

非阻塞套接字

虽然已经SO_LINGER(即linger结构中的l_onoff域设为非零)且设为非零值时,close但还是立即返回,close()调用将以WSAEWOULDBLOCK错误返回。

阻塞套接字

1.已经设置SO_LINGER(即linger结构中的l_onoff域设为非零)且设为零值时,则close()不被阻塞立即执行,不论是否有排队数据未发送或未被确认,且丢失了未发送的数据,给对端发送RST,避免了time_wait状态,但可能导致在2msl内创建一个新的连接,旧的重复分节还在。在远端的recv()调用将以WSAECONNRESET出错。

2已经设置SO_LINGER(即linger结构中的l_onoff域设为非零)并确定了非零的超时间隔,则close()调用阻塞进程,直到所剩数据发送完毕或超时。如果超时了,则close()调用将以WSAEWOULDBLOCK错误返回。

3.设置了SO_DONTLINGER(也就是说将linger结构的l_onoff域设为零);则close()调用立即返回。但是,如果可能,排队的数据将在套接口关闭前发送。所以还是要比直接调用closesocket要等待一些时间的。

SO_RCVBUF 和SO_SNDBUF

1.客户端必须在调用connect之前设置。服务器必须在listen之前设置,已连接套接字是从监听套接字处2继承的。默认的大小一般是8192字节。

SO_RCVTIMEO和SO_SNDTIMEO选项

设置发送和接收超时值,默认是禁止使用的。

SO_REUSEADDR BOOL 允许套接字和一个已在使用中的地址捆绑 ,目的就是地址复用,如广播地址和组播地址使用同一个套                                                 接字

缺省条件下,一个套接字不能与一个已在使用中的本地地址捆绑。

1. SO_REUSEADDR允许启动一个监听服务器并捆绑其众所周知端口,即使以前建立的将此端口用做他们的本地端口的连接仍存在。这通常是重启监听服务器时出现,若不设置此选项,则bind时将出错。举例如在子进程套接字还在,而父进程的监听套接字重启。

2. SO_REUSEADDR允许在同一端口上启动同一服务器的多个实例,只要每个实例捆绑一个不同的本地IP地址即可。对于TCP,我们根本不可能启动捆绑相同IP地址和相同端口号的多个服务器,即使设置了SO_REUSEADDR.

3. SO_REUSEADDR允许单个进程捆绑同一端口到多个套接口上,只要每个捆绑指定不同的本地IP地址即可。这一般不用于TCP服务器。

SO_REUSEADDR允许完全重复的捆绑:当一个IP地址和端口绑定到某个套接口上时,还允许此IP地址和端口捆绑到另一个套接口上。一般来说,这个特性仅在支持多播的系统上才有,而且只对UDP套接口而言(TCP不支持多播)。

1.在tcp服务器中,在调用bind之前设置SO_REUSEADDR选项。

2.在编写一个可在同一时刻在同一主机上运行多次的多播应用程序时,设置SO_REUSEADDR选项,并将所参加多播组的地址作为本地ip地址捆绑。

SO_USELOOPBACK

默认为打开的,相应的套接字将接收在其上发送的任何数据报的一个副本。

如果想禁止环回副本另外一个办法是,shutdown,并设置为SHUT_RD.

TCP_NODELAY

功能:开启TCP_NODELAY将禁用tcp的Nagle算法。

背景:

1.Nagle算法就是如果某个连接上有待确认的数据,立即发送的相应小分组(小就是指小于MSS(最大分节大小)的任何分组)行为不会发生,直到现有的数据被确认。

2.此外还有ACK延滞算法,即ack延迟机制。

fcntl和ioctl函数

 int fcntl(int fd, int cmd, long arg);

fcntl函数功能依据cmd的值的不同而不同。参数对应功能如下:

.          1. 复制一个现有的描述符(cmd=F_DUPFD).

      2.获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD).

3.获得/设置文件状态标记(cmd=F_GETFL或F_SETFL).

4.获得/设置异步I/O所有权(cmd=F_GETOWN或F_SETOWN).

5.获得/设置记录锁(cmd=F_GETLK,F_SETLK或F_SETLKW).

arg:

O_NONBLOCK        非阻塞I/O

O_ASYNC                信号驱动式IO

一般来说,tcp服务器是并发的,udp服务器是迭代的。

udp就一个接收缓冲区存放所有到达的数据报。

unix 网络编程全解相关推荐

  1. 网络编程全解(Java)

    网络编程 1.1 概述 计算机网络: 计算网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信 ...

  2. Java IO编程全解(五)——AIO编程

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7794151.html 前面讲到:Java IO编程全解(四)--NIO编程 NIO2.0引入了新的异步通道的 ...

  3. Java IO编程全解(六)——4种I/O的对比与选型

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7804185.html 前面讲到:Java IO编程全解(五)--AIO编程 为了防止由于对一些技术概念和术语 ...

  4. 《Unix网络编程卷1-套接字联网API》第一个例子编译 不通过问题解决

    <Unix网络编程卷1-套接字联网API>是本好书. 但是第一个例子不是很好编译. 需要如下步骤: 本人机器CentOS 5.4 1.下载源码 unpv13e解压到任意目录 然后按其rea ...

  5. 1.UNIX网络编程卷1:源码配置

    本节主要介绍UNIX网络编程卷1(第三版)在Ubuntu16.04的配置问题,并运行一个简单时间获取客户程序. 1.首先下载源文件,链接如下:UNIX Network Programming Sour ...

  6. Unix——《Unix网络编程》配置unp.h头文件

    <Unix网络编程 卷1>unp.h 头文件及其编译问题 本书源码下载地址 http://www.unpbook.com 解压tar -zxvf unpv13e.tar.gz 其实各个编译 ...

  7. Unix网络编程 chart

    前言 在最初接触网络这一领域的时候,就是傻傻地抱着一本TCP/IP协议详解来学习,主要学习协议的原理并研究协议相关的算法,大家都知道协议纯理论的学习是比较枯燥和复杂的,看着看着就睡着了.由于项目需要, ...

  8. 《UNIX网络编程》第一步:编写自己的daytime客户端,并从daytime服务器获取时间

    编写自己的daytime客户端,并从daytime服务器获取时间 @Author:CSU张扬 @Email:csuzhangyang@gmail.com or csuzhangyang@qq.com ...

  9. Unix网络编程unp.h问题以及Linux中的库

    Stevens的<UNIX网络编程 卷1:套接字连网API>是一本很著名的UNIX网络编程书籍.其中使用了一个unp.h的引用,如果没有设置相应的库的话,即使引入了头文件也是没用的.所以首 ...

  10. Unix网络编程之-------unp.h头文件详细配置-1

    unix网络编程unp.h最详细全面配置说明 今天开始学习Unix网络编程这本大神之作了,由于之前在学习另外一本杰作Unix环境高级编程,遇到过第一个程序编译报错的情况,知道这是大神自己写的头文件在我 ...

最新文章

  1. 色彩为王-CLO带用户发现魅力投影的精彩
  2. 公司间采购的后台配置备忘录
  3. JSP中 input type 用法
  4. java 浅堆 深堆_JVM中的一个小知识点:深堆和浅堆的概念
  5. 吴恩达机器学习1——单变量线性回归、梯度下降
  6. redmi airdots左右耳不串联怎么办_小米AirDots二代4小时售罄,告诉你戴狂卖3500万的耳机是什么感受...
  7. Android之Input子系统事件分发流程
  8. 信息安全之程序实现简单替换加密,并用字母频率统计进行破解
  9. C#无法将顶级控件添加到控件 新的子窗体无法添加到主窗体
  10. 第 14 章 SMS
  11. 项目练习之利用Arraylist 实现学生管理系统(查询,添加,删除,修改)
  12. 芯片设计流程最全讲解
  13. 人行征信中心提醒:不要随意授权征信查询!
  14. 【原创】Codeforces 39A C*++ Calculations
  15. 【Unity】Obi插件系列(三)—— Collisions
  16. 智能卡:常见智能卡芯片型号及其厂家-1
  17. Word将一个文档模板的样式复制到另外一个文档
  18. Psins代码解析之线性误差模型精度验证(test_SINS_error_model_verify.m)
  19. go实现NSQ消息队列的集群部署
  20. 学生DW网页设计作业成品 简单的学校网站制作与实现 HTML+CSS+JS

热门文章

  1. Juniper ScreenOS 路由策略配置
  2. 提升数据建模的10种技术措施
  3. Conky Harmattan : 一款时尚的Linux桌面助手
  4. 2833 奇怪的梦境 未AC
  5. windows交互式登陆
  6. 博客堂服务器转移成功!
  7. uni-app 开发微信小程序,网络断开,无网络情况,刷新检查,重新加载
  8. java oracle spool,oracle之spool详细使用总结
  9. 「开源资讯」Sentinel Go 0.4.0 发布,支持热点流量防护能力
  10. 对路径的访问被拒绝怎么办_工作组计算机无法访问,教您无法访问工作组计算机的解决技巧...