【7】粘包丢包

int sqlite3_get_table(
sqlite3 db, / 要打开的数据库 */
const char zSql, / sql语句 */
char **pazResult, / 成功执行sql语句存放的结果 */
int pnRow, / 执行结果的行数 */
int pnColumn, / 执行结果的列数 */
char *pzErrmsg / 错误信息 */
);
void sqlite3_free_table(char **result);

练习:建立学生表,插入学生信息,并且查询学生信息。

TCP的缺陷(粘包)和UDP的缺陷(丢包)—(面试常考)
tcp粘包与udp丢包的原因及解决方法

一,什么是tcp粘包与udp丢包
TCP是面向流的, 流要说明就像河水一样, 只要有水, 就会一直流向低处, 不会间断.
TCP为了提高传输效率, 发送数据的时候, 并不是直接发送数据到网路, 而是先暂存到系统缓冲,
超过时间或者缓冲满了, 才把缓冲区的内容发送出去, 这样, 就可以有效提高发送效率.
所以会造成所谓的粘包,即前一份Send的数据跟后一份Send的数据可能会暂存到缓冲当中, 然后一起发送。

UDP就不同了, 面向报文形式, 系统是不会缓冲的, 也不会做优化的, Send的时候,
就会直接Send到网络上, 对方收不收到也不管, 所以这块数据总是能够能一包一包的形式接收到,
而不会出现前一个包跟后一个包都写到缓冲然后一起Send。

二、Q:造成TCP粘包的原因
(1)发送方原因

TCP默认使用Nagle算法(主要作用:减少网络中报文段的数量),而Nagle算法主要做两件事:
只有上一个分组得到确认,才会发送下一个分组收集多个小分组,在一个确认到来时一起发送
Nagle算法造成了发送方可能会出现粘包问题

(2)接收方原因

TCP接收到数据包时,并不会马上交到应用层进行处理,或者说应用层并不会立即处理。
实际上,TCP将接收到的数据包保存在接收缓存里,然后应用程序主动从缓存读取收到的分组。
这样一来,如果TCP接收数据包到缓存的速度大于应用程序从缓存中读取数据包的速度,
多个包就会被缓存,应用程序就有可能读取到多个首尾相接粘到一起的包。

Q:什么时候需要处理粘包现象?

如果多个分组毫不相干,甚至是并列关系,那么这个时候就一定要处理粘包现象了
如果发送方发送的多组数据本来就是同一块数据的不同部分,比如说一个文件被分成多个部分发送,这时当然不需要处理粘包现象

4.Q:如何处理粘包现象?
(1)发送方
对于发送方造成的粘包问题,可以通过关闭Nagle算法来解决,使用TCP_NODELAY选项来关闭算法。
使用setsockopt来进行设置套接字属性TCP_NODELAY。
(2)接收方

接收方没有办法来处理粘包现象,只能将问题交给应用层来处理。
	应用层处理:
	1,格式化数据:每条数据有固定的格式(开始符,结束符),这种方法简单易行,
	但是选择开始符和结束符时一定要确保每条数据的内部不包含开始符和结束符。
	2,发送长度:发送每条数据时,将数据的长度一并发送,
	例如规定数据的前4位是数据的长度,先接收传输数据的长度信息,
	应用层在处理时可以根据长度来判断每个分组的开始和结束位置再接收剩下数据。

三,UDP主要丢包原因及具体问题分析
一、主要丢包原因
1、接收端处理时间过长导致丢包:调用recv方法接收端收到数据后,
处理数据花了一些时间,处理完后再次调用recv方法,在这二次调用间隔里,发过来的包可能丢失。
对于这种情况可以修改接收端,将包接收后存入一个缓冲区,然后迅速返回继续recv。

2、发送的包巨大丢包:虽然send方法会帮你做大包切割成小包发送的事情,
但包太大也不行。例如超过50K的一个udp包,不切割直接通过send方法发送也会导致这个包丢失。
这种情况需要切割成小包再逐个send。
 
3、发送的包较大,超过接受者缓存导致丢包:
包超过接收大小数倍,几个大的udp包可能会超过接收者的缓冲,导致丢包。
这种情况可以设置socket接收缓冲。以前遇到过这种问题,我把接收缓冲设置成64K就解决了。
int nRecvBuf=32*1024;//设置为32K
setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
 
4、发送的包频率太快:虽然每个包的大小都小于mtu size 但是频率太快,
例如40多个mut size的包连续发送中间不sleep,也有可能导致丢包。
这种情况也有时可以通过设置socket接收缓冲解决,但有时解决不了。
所以在发送频率过快的时候还是考虑sleep一下吧。
 
5、局域网内不丢包,公网上丢包。
这个问题我也是通过切割小包并sleep发送解决的。
如果流量太大,这个办法也不灵了。总之udp丢包总是会有的,
如果出现了用我的方法解决不了,还有这个几个方法: 要么减小流量,
要么换tcp协议传输,要么做丢包重传的工作。
仿照握手机制设计丢包重传。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 C# 中,网络编程中常见的粘包丢包问题可以通过以下方式解决: 1. 粘包问题 粘包问题通常是由于发送方在一段时间内连续发送了多个数据包,而接收方在接收数据时没有及时处理导致的。解决粘包问题的一种方法是在发送的数据包中添加特定的分隔符,在接收方根据分隔符将数据包拆分成多个消息。 以下是一个简单的示例,演示了如何使用特定的分隔符解决粘包问题: ```csharp using System; using System.Net.Sockets; using System.Text; class Program { static void Main(string[] args) { // 创建一个 Socket 对象 Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 连接服务器 socket.Connect("127.0.0.1", 8888); // 发送数据 string message1 = "Hello,"; string message2 = "World!"; byte[] buffer1 = Encoding.UTF8.GetBytes(message1 + "|"); byte[] buffer2 = Encoding.UTF8.GetBytes(message2 + "|"); socket.Send(buffer1); socket.Send(buffer2); // 接收数据 byte[] buffer = new byte[1024]; int count = socket.Receive(buffer); string response = Encoding.UTF8.GetString(buffer, 0, count); Console.WriteLine(response); // 关闭 Socket 连接 socket.Shutdown(SocketShutdown.Both); socket.Close(); } } ``` 在上面的示例中,我们在发送的数据包中添加了分隔符 `|`,在接收方根据分隔符将数据包拆分成多个消息。这样可以保证每个消息都是完整的,避免粘包问题。 2. 丢包问题 丢包问题通常是由于网络传输中数据包丢失导致的。解决丢包问题的一种方法是在发送的数据包中添加序号,接收方在接收数据时根据序号判断是否有数据包丢失并进行重传。 以下是一个简单的示例,演示了如何使用序号解决丢包问题: ```csharp using System; using System.Net.Sockets; using System.Text; class Program { static void Main(string[] args) { // 创建一个 Socket 对象 Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 连接服务器 socket.Connect("127.0.0.1", 8888); // 发送数据 int seq1 = 1; int seq2 = 2; string message1 = "Hello,"; string message2 = "World!"; byte[] buffer1 = Encoding.UTF8.GetBytes(seq1 + "|" + message1); byte[] buffer2 = Encoding.UTF8.GetBytes(seq2 + "|" + message2); socket.Send(buffer1); socket.Send(buffer2); // 接收数据 byte[] buffer = new byte[1024]; int count = socket.Receive(buffer); string response = Encoding.UTF8.GetString(buffer, 0, count); Console.WriteLine(response); // 关闭 Socket 连接 socket.Shutdown(SocketShutdown.Both); socket.Close(); } } ``` 在上面的示例中,我们在发送的数据包中添加了序号,接收方可以根据序号判断是否有数据包丢失并进行重传。这样可以保证数据的完整性,避免丢包问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值