写在前面
预备知识
- 本文的目的是写回显服务器,在撸代码之前,先来个热身。
IP地址是什么
IP地址有IPV4、IPV6之分,一般不特俗说明,默认就是IPV4。
IP地址是用来标识不同的主机,每个主机都有唯一的IP地址;
对于IP4来说,IP地址是一个4字节,32位整数;
IP地址用“点分”制表示,如:192.168.1.11(用点分割的每个数范围0~255)。
源IP地址&目的IP地址
很容易理解,都是地址,和寄快递的收发地址一样,从上海发往西安的快递,源IP就是上海,目的IP就是西安。
端口号是什么
- 端口号是传输层协议内容
端口号是2字节196位整数;
端口号用来标识一个进程,告诉操作系统,当前数据要交给哪一个进程来处理;
一个进程可以绑定多个端口号,但是一个端口号不可以绑定多个进程。
源端口号&目的端口号
在源IP&目的IP中,我们用的寄快递的例子帮助理解,在这里,还是用发快递帮助理解。源IP与目的IP标识了发件人地址和收件人的地址,地址有了,那么包裹就会交给快递员运送每个,快递员都有一个工号,工号是唯一的。这就对应了数据传输过程中,由哪个进程来处理数据。再来到寄快递问题上,有的快递包裹比较大,这就要多个快递员来运输,那么一个包裹由多个快递员运输,记在物流信息上就是这样的格式:一个包裹的目的地 + 多个快递员工号;这家公司接的都是大包裹,一个快递员只能送一个包裹。对应到网络传输中,就是一个进程可以绑定多个端口号,但一个端口号不可以绑定多个进程。
函数介绍
- 为后面撸代码介绍几个函数。
网络字节序:
在C语言中我们知道,内存中的数据存储有大小端之分;数据在磁盘中存储也有大小端之分,在这里我还想啰嗦一个C语言问题,怎样判断自己的计算机内存是大端字节序还是小端字节序存储方式?[假装思索……]
- 大小端判断很有可能成为你将来的面试题。以前我总结过这样的问题。
- 以后再附上链接:哈哈
- (只想引入下面一句话)在网络数据流中同样有大小端之分,那么如何定义网络数据流的地址呢?
【看图理解】
【看图说话】
- 如果发送主机是小端,就要准换成大端再发送,如果是大端,直接发送即可。
为了使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。
1 |
|
调用函数就能解决存储字节序不统一的问题
socket编程常见API:
这部分只把函数列出来,详细介绍请戳作者下面博客:
请戳: socket套接字总结
1 | //创建socket文件描述符 (TCP/UDP,客户端+服务器) |
sockaddr结构:
socket API是一 层抽象的网络编程接口 ,适用于各种底层网络协议,如IPv4、IPv6.然而, 各种网络协议的地址格式各不相同。
注意:socket API可以都用 struct sockaddr *类型表 , 在使用的时候需要强制转化成sockaddr_in; 这样的好处是程序的通用性, 可以接收IPv4, IPv6, 以及UNIX Domain Socket各种类型的sockaddr结构体指针做为参数。
UDP协议
通过上面的学习对UDP有个直观的认识,再详细讨论以下几点:
- 无连接
知道目的端的IP和端口号就能传输,不需要建立连接。
- 不可靠传输
没有确认机制,没有重传机制,如果因为网络故障无法发送到对方,UDP协议层也不会给应用层返回任何错误信息。
- 面向数据报
不能够灵活的控制读写数据的次数和数量。
- 以上几点在代码中还能得到学习和理解。
服务器和客户端是怎么运行起来的?
先说说什么是回显服务器:
回显服务器是最简单的服务器,客户端发起请求,服务器收到请求,然后客户端发送什么内容,服务器就给客户端返回什么内容。
- 服务器:
1、创建socket
2、绑定端口
3、循环的读取数据
4、针对读取到的数据进行计算和处理
5、把处理后的结果发回客户端
- 客户端:
1、创建socket文件
2、给服务器发送请求
3、从服务器中读取结果。
- 有了步骤,实现起来就只需要把步骤翻译成Code了:
服务器实现
1 |
|
客户端实现
1 |
|
问题思考
1、UDP协议的特点以及和TCP协议的区别?
2、UDP连接建立过程分析、TCP呢?
3、UDP协议是不可靠的,为什么还要使用?
本文链接: http://askunix.github.io/2018/05/22/基于UDP协议的回显服务器/
版权声明:本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可,转载请注明出处!