Socket编程,如何保证外网环境下通信可靠无误
来源:互联网 发布:js判断一个月有多少天 编辑:程序博客网 时间:2024/06/06 03:10
Socket.Send是一个同步阻塞函数,表是向网络套借口发送数据,原型是:int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags);这里面要注意返回值哦!很多初级程序员,以为只要调用这个函数,发送数据的事情就万事大吉了,这是因为在编程环境中,都是本机或100M内网,网络速度足够快,一般99%不会出现问题。但如果你到Internet环境中的时候,那就漏洞百出了。
这里首先要注意,此函数返回的是已经成功发送的字节数,你缓冲区的Buffer如果大于此返回值,这样数据就没有发送完毕。如果你要包装一个函数,一定要发送完你的Buffuer中的数据,那你建以你采用下面的方案:
public bool MySendData(const byte[] Buffer, Socket theSocket)
{
int SendPos = 0;//缓冲区发送的开始位置
int OneDataSendLen = 0;//每次发送的数量
while (SendPos < Buffer.Length)//发送完毕
{
OneDataSendLen = theSocket.Send(Buffer, SendPos, Buffer.Length - SendPos, SocketFlags.None);
SendPos += OneDataSendLen;//位置往后移动
}
return true;
}同样的道理,Receive函数的包装方式也得调整,如果你接受一个固定大小的数据包,包装方式如下:
public byte[] MyReceive(const int PackLenth,Socket theSocket)
{
byte[] Buff = new bytePackLenth
int RecPos=0;
while (RecPos < PackLenth)//未接受完毕,继续接收
{
OneDataSendLen = theSocket.Receive(CmdBuff, RecPos, CmdLength - RecPos, SocketFlags.None);
RecPos += OneDataSendLen;
if (RecPos >= PackLenth)
break;
}
return Buff;
}
上面的Send和Receive是同步阻塞方法,一般在为了设计效率问题和灵活性,在做大规模高效的通信软件的情况下,一般是不会采用的,所以大家一般要用到一步方法BeginSend,BeginReceive方法。
先看看他们的原型:
public IAsyncResult BeginSend(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, object state);
其它函数都差不多,关键多了一个AsyncCallback和State参数,AsyncCallback这表示此次发送完成后(注意是此次完成,不一定是所有数据已发送完成),需要执行的回调函数,其类 型为:void AsyncCallback(IAsyncResult ar);
另外还有一个Object 类型的State参数,这个参数用传送发送参数,并最终传递到AsyncCallback函数中,为此我们构建一个对象,
public class TDatagram
{
public int OffSet = 0;
public int OneLength = 1024 *8;//2
public int Length;
public byte[] Buffer;
public Socket TheSocket;
public bool IsObj;
}
//异步发送数据
public bool AsnySend( byte[] Buffer, Socket TheSocket)
{
TDatagram Datagram = new TDatagram();
Datagram.OffSet = 0;
Datagram.Length = Buffer.Length;
Datagram.Buffer = Buffer;
Datagram.TheSocket = TheSocket;
TheSocket.BeginSend(Buffer, 0,Buffer.Length, SocketFlags.None, new AsyncCallback(CallBackSendData), Datagram);
}
// 回调函数需要执行EndSend();
private void CallBackSendData(IAsyncResult IAsync){
TDatagram Datagram = (TDatagram)(IAsync.AsyncState);
Datagram.OffSet += Datagram.TheSocket.EndSend(IAsync);//回调结束此次发送,返回此次发送的字节数
if (Datagram.OffSet < Datagram.Buffer.Length)//没有发完,继续发送
{
Datagram.TheSocket.BeginSend(Datagram.Buffer, Datagram.OffSet, Datagram.Buffer.Length - Datagram.OffSet, SocketFlags.None, new AsyncCallback (CallBackSendData), Datagram);
}
}
就是说如果本次还没有发送完毕,需要继续调用发送方法,如果网络速度很慢,还可能出现反复调用发送方法。
至于异步接受方法的实现,大家可以参考发送的方法了,在此我不再做描述了。
本人曾经给海外朋友设计了一个大型高并发的实时赔率传送软件,基本就是采用上面的思路,实现了不同地区的数完整传输,没有出过差错,可以说是经过检验的。本文希望对大家设计自己专用的通信程序的时候做参考之用。如果一知半解,想当然,你的程序肯定漏洞百出!
- Socket编程,如何保证外网环境下通信可靠无误
- Android架构 系统如何保证运行无误
- TCP如何保证可靠数据传输
- TCP如何保证可靠传输
- TCP如何保证可靠传输
- TCP如何保证可靠传输
- socket编程(一)使用SOCK_STREAM建立可靠通信
- socket编程(一)使用SOCK_STREAM建立可靠通信
- Linux环境下socket通信
- TCP如何保证可靠传输的
- TCP协议如何保证可靠传输
- TCP是如何保证数据可靠传输
- TCP协议如何保证可靠传输
- Storm如何保证消息的可靠处理
- Storm如何保证可靠的消息处理
- TCP是如何保证可靠数据传输的?
- TCP是如何保证可靠数据传输的?
- Storm如何保证可靠的消息处理
- 重载 new 和 delete 运算符
- Java虚拟机的架构(二)
- RN 学习中遇到的的问题
- 塔防大战unity5.5版本系列(part7)
- nginx学习笔记3 简单的负载均衡(正反向代理)
- Socket编程,如何保证外网环境下通信可靠无误
- 将博客搬至CSDN
- 洛谷P1468 派对灯 Party Lamps
- 反转链表
- 正确使用join语句
- Sticks (剪枝)
- 【JZOJ3737】【NOI2014模拟7.11】挖宝藏(treasure)
- Linux 服务器安装MySQL数据库
- 百度富文本编辑器的上传图片的路径问题