![](https://img-blog.csdnimg.cn/20201014180756925.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
网络编程
Function_18
这个作者很懒,什么都没留下…
展开
-
0. 网络编程目录
至今已经在第二次写网络编程的博客了, 去年将网络分析和系统编程一起进行整理的, 而且没有对每一个知识点进行归纳和总结. 前段时间还是又回顾了TCP编程的一点基础, 为了以后回顾还有学习网络编程的看到写的博客后能够成系列的来学习, 还是决定还是重新整理一下更好.现在模块分为四个部分 : TCP通信, TCP协议(计算机网络的部分知识), UDP通信, HTTP 通信.整个板块的目的就在于如何实...原创 2019-05-16 12:23:32 · 659 阅读 · 0 评论 -
26. TCP协议之紧急模式
前面我们分析过TCP的ACK, RST等, 本节来分析URG.TCP报文段首部格式注意 : TCP虽然是面向字节流的, 但是TCP传送的数据单元却是报文段.消息被设置为紧急时会把TCP状态标记为URG, 同时还会设置紧急指针.紧急模式在套接字选项中找不到关于URG的描述, 那么该消息又怎样被标记为紧急呢? 别急, 消息标记为紧急数据这个在最开始实现套接字通信中有说到过. 紧急标...原创 2019-05-07 09:51:58 · 807 阅读 · 0 评论 -
20. 从编程方面分析三次握手过程
前面分析过了理论的三次握手的过程以及为什么需要三次握手, 本节我们再以socket编程的方面分析三次握手的过程.从编程角度分析三次握手三次握手, 三个函数, 分别是listen, connect和accept.服务端调用listen函数一直监听网络中有没有要与服务端连接的客户端, 并且**listen初始化未决连接队列**.未决连接队列分为未完成连接队列和已完成连接队列, 这里是我...原创 2019-05-07 09:48:44 · 657 阅读 · 0 评论 -
18. TCP/IP协议族
TCP/IP协议族不像理论的协议关系有7层, 前者只有四层. 自底而下分别是 : 数据链路层, 网络层, 传输层, 应用层; 每一层对应不同的功能. 本节只是简单的介绍一下关于这四层协议的功能.数据链路层数据链路层实现了网卡接口的网络驱动程序, 以处理数据在物理媒介(以太网等)上的传输过程.数据链路层常用的是连个协议 : ARP协议和RARP协议.网络通信看上去是上层之间的直接通...原创 2019-05-07 09:44:13 · 338 阅读 · 0 评论 -
14. TCP套接字之shutdown函数
前面我们虽然解决了困惑我们很久客服端的问题, 但是虽然解决了但是该客服端还有更加大的隐患存在, 接下来我们就来看一下问题所在和问题解决办法.问题浮现使用前面IO复用之select 的客服端和服务端都改写成的完整代码做实验.完整代码 : select_server_client.c服务端运行: ./a.out 1 8080 127.0.0.1客服端运行:./a.out 2 808...原创 2019-05-07 09:38:40 · 1030 阅读 · 0 评论 -
12 TCP套接字之IO分离
前面通过信号捕捉也没有完美的解决客服端阻塞的问题, 那么本节我们通过将客服端的IO操作分离的办法来解决这个困惑我们很久的bug吧.IO分离第一次听到 IO分离 肯定会感觉很陌生, 不急, 下面我会解释的.IO分离实际是将 read逻辑操作(也就是读操作) 和 write逻辑操作(也就是写操作) 的实现分离开. 分离技术有多种, 本节也仅仅介绍一种简单.疑惑在SIGPIPE信号中我们...原创 2019-05-07 09:08:55 · 412 阅读 · 0 评论 -
11 TCP套接字之SIGPIPE信号
前面我们解决了并发服务端的问题, 但是还是没有解决掉客服端的bug.问题重现我们以上一节的代码为例浮现这个bug.完整代码 : fork_SIGCHLD.c可能你已经忘了客服端的问题了, 这里在重新说明一下 : 当建立连接后, 服务端主动关闭后, 客服端并没有立即退出, 而是处于阻塞状态直到有输入才会退出.问题分析分析问题的时, 应该先来看一下抓包的情况.问题基本也能分析出...原创 2019-05-07 09:02:11 · 679 阅读 · 0 评论 -
进程最大打开文件描述符个数
不过在看下节之前, 首先知道在本机下打开的文件描述符个数的个数不能超过 1024, 除去3个输入输出还有epoll的文件描述符, 所以程序传入的最大打开文件描述符的参数不能超过 1020. 如果超过服务端报错结果如下 :临时最大进程最大打开文件描述符通过查看一个进程的最多打开个数, ulimit -n设置临时设置打开个数 :limit -n10001在普通用户下最多能够临时打...原创 2019-05-06 23:26:31 · 4010 阅读 · 0 评论 -
45. connect 实现定时
我们需要先连接 getaddrinfo, 而 getaddrinfo 的特性实在太多, 本节也仅仅只是简单的做一个小结, 如果想要了解更加全面可以参考 unp 第245页.getaddrinfo 函数getaddrinfo 函数是与协议无关 (TCP, UDP都可以) 并且不仅支持 IPV4 还支持 IPV6 .函数原型 :#include <netdb.h>int g...原创 2019-05-08 16:26:29 · 328 阅读 · 0 评论 -
44. 最大保持TCP连接个数
前面通过IO复用实现了 connect 的定时, 本节使用 connect 非阻塞验证进程 能保持多少 TCP连接.非阻塞式非阻塞 connect 还能用来测试服务端的抗压能力, 当然使用阻塞 connect 也能够保持多个 TCP 连接, 但效率没有非阻塞高. 可以看出来同一时间阻塞式的必须保证一个连接成功才会执行后一个连接, 非阻塞式能够在同一时间保证多个连接的进行.完整代码 : ...原创 2019-05-08 16:23:56 · 629 阅读 · 0 评论 -
43. TCP套接字之connect非阻塞
本节来将客户端的connect阻塞式改为非阻塞式. 这样可以同时向服务端发起多个连接并一起进行处理, 非阻塞connect一般用来测试服务端的抗压能力.connect 非阻塞用途connect设置为非阻塞之后会立即返回 设置errno为 EINPROGRESS 错误, 表示连接操作正在进行中, 但是仍未完成连接; 同时TCP的三次握手操作继续进行. 之后, 可以调用 select 来检查...原创 2019-05-08 16:21:32 · 875 阅读 · 0 评论 -
42. TCP套接字之accept非阻塞
本节来理论性的了解一下关于服务端 accept 非阻塞.阻塞 accept服务器在繁忙过程时, 在建立三次握手之后, 调用accept之前, 如果出现客户端突然断开连接的情况, POSIX 指出这种情况 errno 设置为 CONNABORTED.如: 三次握手之后, 客户端发送 RST后断开连接, 之后服务端调用accept准备执行连接但并不知道对端已经关闭, 这个时候accept就...原创 2019-05-08 16:20:14 · 2708 阅读 · 0 评论 -
41. 非阻塞IO
前面我们所使用的IO都是阻塞式的, 当然, 默认也是阻塞式的. 不过我们也可以设置文件描述符将阻塞式变为非阻塞式. 我们为什么会将阻塞式转为非阻塞式呢? 肯定是有好处的, 而本节就先简单介绍一下关于非阻塞式.阻塞式先来了解一下阻塞式.阻塞式 : 进程运行到阻塞式的函数时会被投入睡眠切换执行其他程序, 直到被中断或者被唤醒才会切换回程序继续执行.阻塞式的问题 :对于CPU来说IO操作...原创 2019-05-08 16:18:21 · 515 阅读 · 0 评论 -
29. 套接字选项之SO_REUSEADDR
在TCP四次挥手中有time_wait状态, 该状态使得进入该状态的端口在2MSL的时间内不能再次被绑定, 这对客服端并没有太大的影响, 这个对服务端的影响就很大了. 一般我们编写的服务端连接都很少, 而高并发服务器对于端口立即绑定是必须的, 毕竟服务端也可能掉线而等上2MSL的时间肯定不允许.SO_REUSEADDR 选项允许绑定处于 TIME_WAIT 状态的套接字地址允许在...原创 2019-05-07 09:55:04 · 331 阅读 · 0 评论 -
30.TCP协议之TCP缓冲区
每个套接字都会有一个发送缓冲区和接收缓冲区, 这样的功能保证了TCP的容错性, 毕竟数据有保存可以重传.TCP缓冲区对TCP来说套接字接收缓冲区限制了TCP通告对端的窗口大小. 并且, 接收缓冲区不存在溢出问题, 因为不允许发送超过本端所通告窗口大小的数据, 这就是TCP流量控制. 如果对端发送了超过窗口大小的数据, 则接收端将直接丢弃.UDP缓冲区既然说了TCP缓冲区, 顺便提一...原创 2019-05-07 09:56:36 · 2732 阅读 · 1 评论 -
34. UDP协议
接下来准备简单探讨一下关于UDP套接字编程.UDP头部UDP是面向报文.UDP的头部是固定8字节, 分别是 : 源端口, 目的端口, 长度, 检验和.校验和是用来保证数据的安全.UDP协议UDP是一种无连接的传输层协议, 提供面向事务的简单不可靠信息传送服务, 适合于一次传输少量数据; 在网络环境较差的情况下, UDP协议数据包丢失会比较严重.不可靠 :不提供报文到达确认...原创 2019-05-07 10:00:44 · 409 阅读 · 0 评论 -
gdb 多线程和多进程调试
gdb 多进程和多线程调试多进程调试info inferiors : 显示当前的多进程信息. 前面有 * 表示当前调试的进程inferiors num : 指定当前调试的进程. num表示当前跳转到调试的进程番号.如果要调试子进程的话, 可以用 ps 命令查看在使用该命令执行指定进程的调试set|show follow-fork-modeshow ...原创 2019-05-10 15:49:18 · 486 阅读 · 0 评论 -
53. 线程池
一般在web服务端使用线程池是比较常见的, 本节呢, 就已以实现一个简单的web服务端为目标, 仅仅实现GET请求, 最多在加上POST请求.如果对web服务端并不熟悉的, 可以回过头去看一下http请求与应答以及一个500行左右的web服务端源码tinyhttpd(整理了源码以及修改和加注释后的linux版本).线程池主要函数线程池完整代码位置 : threadpool因为线程池的...原创 2019-05-10 15:19:54 · 356 阅读 · 2 评论 -
52. 线程-IO复用(EPOLLONESHOT)
线程怎么与IO复用联系起来, IO复用中创建线程? 还是线程中IO复用? 这个问题用在进程也是一样的. 其实两种方式都可以. 本节采用在 IO复用中创建线程, 接下来就来看看具体怎么实现的吧.epoll 的EPOLLONESHOT事件还记得 epoll 的 event 可设置的状态吗? 忘了也不急, 这里将 IO复用之epoll函数 的状态粘贴过来.event值描述...原创 2019-05-10 15:17:54 · 366 阅读 · 0 评论 -
51. 线程-服务端
在最开始实现并发服务端的时候, 最开始想到的办法便是使用多进程, 使每个 TCP 连接对应一个进程; 之后我们又将多进程并发改写成了 IO 复用的方式实现了相同的功能; 但现在唯一没有将服务端改写成线程, 本节就来改写服务端.线程服务端在改写成多线程之前, 要对 [线程创建], [线程同步]以及线程终止有所了解才行.主函数仅仅只是将连接后回射操作交给线程即可 :int main(in...原创 2019-05-10 15:14:41 · 261 阅读 · 0 评论 -
50. 进程池
一般进程池和线程池都是并发编程中常见的, 如nginx采用进程池, 也有实现协程降低上下文切换的代价等等, 使用和实现这些方法都是为了提高我们服务端的并发能力.进程池和线程池都是避免服务端频繁的创建进程(线程), 毕竟创建进程(线程)的代价很大. 所以可先在程序运行时便分配出一定的进程(线程)数, 如果有事件就绪便可以直接调用分配好的进程, 让进程池中的进程区处理事件, 事件处理结束后进...原创 2019-05-10 15:12:31 · 277 阅读 · 0 评论 -
49. HTTP 请求/应答
HTTP 协议是 Hyper Text Transfer Protocol (超文本传输协议) 缩写, 并且是基于 TCP/IP 通信协议来传递数据.HTTP 协议特点无连接 : 每次进行一次 HTTP 通信. 服务器处理完客户的请求并收到客户的应答后立即断开连接, 这种方式被称为短连接. 采用这种方式可以节省传输时间, 但是连续传输使用短连接就比较消耗资源. (http1.1后有长连...原创 2019-05-10 15:10:16 · 2790 阅读 · 0 评论 -
48. 半同步/半异步
本节说到的半同步与半异步跟同步和异步并不是一个概念, 请不要混淆了. 也为了避免混淆, 下面也会对同步和异步做一个简要的说明.同步/异步同步和异步是属于IO模型中, 前面已经对IO模型有过接触了( 如 非阻塞IO[1]).同步 : 内核通知进程有数据到来, 进程从内核空间中将数据复制到应用空间中.异步 : 内核将数据复制到指定的空间中后通知进程, 进程只管处理数据. 异步不会阻塞....原创 2019-05-10 15:08:57 · 867 阅读 · 0 评论 -
47. web 客户程序
前面铺垫了非阻塞 connect 以及 HTTP 请求, 本节就已 unp 书上的例子实现一个简单的 web 客户端程序.客户程序使用非阻塞式connect 保证同时能建立多个 TCP 连接.如果使用阻塞式 connect, 每次都必须等待上一个连接成功后才能建立下一个连接; 而我们所写的客户程序只是将第一个连接单独执行, 之后的多个连接再并行连接.完整代码 : client_web...原创 2019-05-10 15:07:27 · 343 阅读 · 0 评论 -
46. 域名解析
前面我们使用的所有客户端建立连接都是在知道对方的 IP 地址基础上进行的. 但是如果我们需要使用前面的客户端程序与网页建立连接难不成还要记住该网页的 IP 不成?当然. 有过网络基础上肯定知道 DNS域名服务器. 该类域名系统通过主机名就可以查询得到其 IP 地址, 之后便顺利进行连接. 当然操作系统也为我们提供这类系统函数, 保证我们只需要通过主机名就能与网页发起连接.gethostna...原创 2019-05-10 15:05:10 · 335 阅读 · 0 评论 -
35. UDP套接字之无连接通信
如同TCP通信一样, UDP套接字也有专门的发送和接收数据的函数对应. TCP是recv和send两个函数负责收发, UDP是通过recvfrom和sendto两个函数负责收发数据.recvfrom和sendto函数函数原型:#include <sys/socket.h>ssize_t recvform(int sockfd, void *buff, size_t nb...原创 2019-05-07 10:04:16 · 420 阅读 · 0 评论 -
40. socket 就绪条件
在实现网络通信前, 先来了解一下socket套接字什么时候就绪(可读可写). 第一次学习socket只需要明白我用红色标记的条件就行.缓冲区每个套接字接收区缓存 (用于读) 和发送区缓存 (用于写) :接收区缓存: 接收数据, 从内核缓冲复制到用户应用程序数据缓冲区.发送去缓存: 用户应用程序数据缓冲区复制到内核缓冲区, 等待发送.每个套接字都有接收缓存区低水位标记(用于读)和...原创 2019-05-08 13:04:59 · 342 阅读 · 0 评论 -
39. TCP套接字之日志记录
前面我们实现了完整的TCP通信, 现在我们可以来考虑为通信加上日志记录的功能. 实现日志记录可以直接将数据写入文件中.管道实现日志记录这里采用管道实现进程间通信, 通过一个单独的进程来记录日志.主要用到的就是文件的创建, 无名管道以及进程间通信的方法.以下是删除了大部分的服务端代码, 只留下了修改过后的代码. 这里采用的是带缓冲的fwrite函数实现向文件里写入数据. 因为采用的fw...原创 2019-05-08 12:57:20 · 750 阅读 · 0 评论 -
38. TCP套接字之标准IO
上节实验了关于标准IO能够明显提升运行效率, 那么本节就来将之前使用的系统IO改为标准IO试试.修改为标准IO本节修改的代码是epoll中修改后的代码. 其实就只需要把客服端的read函数换成标准IO的fgets即可.while(1){ testrfds = rfds; select(sockfd + 1, &testrfds, NULL, NULL, NULL); if(...原创 2019-05-08 12:54:46 · 253 阅读 · 0 评论 -
22. TCP协议之四次挥手
TCP创建的过程和释放的过程都是通过TCP/IP协议栈自动完成的. 本篇就主要是分析TCP释放过程.TCP报文段首部格式注意 : TCP虽然是面向字节流的, 但是TCP传送的数据单元却是报文段.本篇我们主要会涉及到TCP首部的 : FIN.四次挥手的过程连接释放需要发送4次报文才能完成. 这是因为TCP连接是全双工的, 每一端都需要对读写部分分别进行关闭才行. 当一端关闭读/写或者都...原创 2019-02-20 21:56:45 · 2113 阅读 · 0 评论 -
21. TCP协议之三次握手抓包
上一节分析了三次握手的原理, 而本节来实际抓包来查看三次握手的过程.环境操作系统 : linux抓包软件 : wireshark抓包操作实验代码 : service_client.c服务端输入 :./a.out 1 8080 192.168.1.16客服端输入 :./a.out 2 8080 192.168.1.16如果不知道信息哪一个网卡的话, 可以选择any, 然后加上...原创 2019-02-20 21:54:05 · 897 阅读 · 0 评论 -
19. TCP协议之三次握手
TCP创建的过程和释放的过程都是通过TCP/IP协议栈自动完成的. 本篇就主要是分析TCP创建过程.TCP报文段首部格式注意 : TCP虽然是面向字节流的, 但是TCP传送的数据单元却是报文段.本篇我们主要会涉及到TCP首部的 : 序号(初始序号), 确认号, ACK以及SYN.三次握手的过程TCP协议的连接需要三次握手才能完成, 分别是 :客户端先初始化一个随机初始序号(ISN...原创 2019-02-20 21:51:02 · 380 阅读 · 0 评论 -
09 TCP套接字之并发服务端
前面实现了简单的网络通信, 但是随之而来还是很多的问题. 比如为什么只能建立一个连接; 为什么服务端先断开会有客户端还没有响应断开等等. 问题我们一个个来解决, 本节就先来解决连接问题.多进程我们可以为每一个连接重新创建一个进程, 这样就可以实现每次只能连接一个的问题了. 同样多进程可以解决, 那么多线程也可以解决, 而现在先以进程解决, 后面我们再来以线程解决.一般我们都是将客服端和服务端...原创 2019-02-19 21:48:20 · 469 阅读 · 0 评论 -
10 TCP套接字之SIGCHLD信号
上节发现了新的fork程序还有问题, 本节就来解决这个问题.回顾问题将两个客户端关闭, 结果呢, 服务端的两个子进程的资源没有被回收从而成为了僵尸进程了. 父进程没有正确的回收子进程的资源, 所以人家就成了僵尸.其实在apue书中就讲到过, 子进程退出后父进程会收到子进程的SIGCHLD信号, 但是该信号父进程默认是忽略的. 而现在想要解决这个问题, 就必须让父进程捕捉该信号, 并作出处理...原创 2019-02-19 21:42:10 · 446 阅读 · 0 评论 -
08 TCP套接字之通信
介绍了5中最重要也是最基础与套接字相关的函数, 本节就来运用这5个函数实现一个最简单的网络通信吧.回射思路回射, 将客户端发送过来的所有数据全部原封不动的发送回去. 可以使用write和read函数来实现, 客户端使用write函数向套接字中写数据, 对端用read函数读数据并调用write函数又将数据写回套接字, 客户端最后使用read读即可.recv和send函数回射可以用上面分析到的...原创 2019-02-19 21:31:29 · 585 阅读 · 0 评论 -
07 TCP套接字之accept函数
前面介绍listen函数介绍过未完成连接队列和已完成连接队列, 已完成连接队列是跟对端的connect函数保持了连接, 但是这样的连接只是单方向的. 服务端并没有确切想要跟客户端通信, 想要两端能够持久保持连接还能通信, 就需要让服务端调用accept函数函数原型#include &lt;sys/socket.h&gt;int accept(int sockfd, struct sockad...原创 2019-02-19 21:29:50 · 2202 阅读 · 0 评论 -
06 TCP套接字之listen函数
前面介绍了客服端通过调用connect函数就能向服务端请求连接, 但是服务端如果不开启监听服务的话就根本不知道对端想要与之建立连接. 要想知道客户端想要连接就得调用listen函数函数原型#include &lt;sys/socket.h&gt;int listen(int sockfd, int backlog);成功 : 返回0;失败 : 返回-1.函数语义假设由socket函...原创 2019-02-19 21:28:55 · 1183 阅读 · 0 评论 -
05 TCP套接字之connect函数
前面介绍了socket函数获取文件描述符, bind函数是为了让本地协议与套接字进行绑定, 本节介绍让客户端主动与服务端进行连接的connect函数.函数原型connect函数建立与TCP服务器的连接.#include <sys/socket.h>int connect(int sockfd, const struct sockaddr* addr, socklen_t add...原创 2019-02-19 21:27:49 · 1221 阅读 · 0 评论 -
04 TCP套接字之bind的函数
前面介绍了socket函数, 本节介绍bind函数. 该函数是网络通信时服务端必不可少的函数.函数原型bind函数把一个本地协议地址赋予一个套接字.#include &lt;sys/socket.h&gt;int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);成功 : 返回0.失败 : 返回-1....原创 2019-02-19 21:25:45 · 1998 阅读 · 0 评论 -
03 TCP套接字之socket函数
在执行网络I/O时, 要做的第一件事就是调用socket函数.函数原型#include &lt;sys/socket.h&gt;int socket(int family, int type, int protocol);成功 : 返回非负描述符.失败 : 返回-1, 设置errno的值.函数错误时返回-1, 但是也会设置相应的errno的值 :值含义EACCE...原创 2019-02-19 21:23:56 · 610 阅读 · 0 评论