【手机网络游戏 编程】C#异步socketAPI调用 处理数据的流程
之前客户端在网络条件好的时候,运行没问题.但是有时候手机的网络不稳定,接受数据可能不稳定,导致接受数据错误,一直都不知道,原来是接受数据处理的不够好!
现在更改过后的接受数据的逻辑如下:
//接收
public void Receive(int length, bool tag, byte[] head)
{
if (clientSocket != null && clientSocket.Connected)
{
StateObject stateObject = new StateObject(length, clientSocket, tag, head);
clientSocket.BeginReceive(stateObject.sBuffer, , stateObject.sBuffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), stateObject);
}
} //接收回调
private void receiveCallback(IAsyncResult asyncReceive)
{
try
{
//异步接收的结果
StateObject stateObject = (StateObject)asyncReceive.AsyncState; if (stateObject.sSocket == null)
{
m_CallReceive(false, Error_Socket.SOCKET_NULL, "", null, "");
return;
}
else if (!stateObject.sSocket.Connected)
{
m_CallReceive(false, Error_Socket.SOCKET_UNCONNECT, "", null, "");
Debug.Log("连接断开");
return;
}
//接收标示
if (stateObject.spkgTag)
{
#region This_TIME_RECV_PKG_HEAD
int recv_this_time_length = stateObject.sSocket.EndReceive(asyncReceive);
//接收到的数据
byte[] m_recv_Buffer = new byte[recv_this_time_length];
ComClass.MemCpy(m_recv_Buffer, stateObject.sBuffer, , recv_this_time_length); mypkg_head pkg_head_tmp = new mypkg_head();
pkg_head_tmp.unpacket(m_recv_Buffer);//解析数据包 //接收消息长度为10
if (pkg_head_tmp.length == && recv_this_time_length>=)
{
m_CallReceive(true, error_Socket, "", m_recv_Buffer, "");
}
else if(pkg_head_tmp.length> && recv_this_time_length>=)
{
Receive(pkg_head_tmp.length - recv_this_time_length, false, m_recv_Buffer);
return;
}else{
Debug.LogError("######## ERROR PKG_HEAD ERROR [ "+recv_this_time_length+" bytes] #############");
}
#endregion }
else//数据
{
#region THIS_TIME_CONTINUE_RECV_DATA
int have_recv_length=stateObject.sheadBuffer.Length;
int recv_this_time_length = stateObject.sSocket.EndReceive(asyncReceive);
//接收到的数据
byte[] m_recv_Buffer = new byte[recv_this_time_length + have_recv_length];
//////m_recv_Buffer = ComClass.ConnectBytes(stateObject.sheadBuffer, stateObject.sBuffer);
ComClass.MemCpy(m_recv_Buffer, stateObject.sheadBuffer, , stateObject.sheadBuffer.Length);
ComClass.MemCpy(m_recv_Buffer, stateObject.sBuffer, stateObject.sheadBuffer.Length, recv_this_time_length); mypkg_head pkg_head_tmp = new mypkg_head();
pkg_head_tmp.unpacket(m_recv_Buffer);//解析数据包 Debug.Log("[length="+pkg_head_tmp.length+"][type="+pkg_head_tmp.type+"][command="+pkg_head_tmp.command+"][uid="+pkg_head_tmp.uid+
"] 前面已经接受了"+have_recv_length+"个字节;本次接受"+recv_this_time_length+"个字节; 已经累计接受了"+m_recv_Buffer.Length+"个字节");
//sbuffer分配的大小 比实际接受到的小,那么就得继续接受完!!!
//##if(stateObject.sBuffer.Length!=recv_this_time_length && false){
//## Debug.LogError("#################### ERROR:stateObject.sBuffer.Length["+stateObject.sBuffer.Length+
//## "]!=recv_this_time_length["+recv_this_time_length+"] ####################");
//## return;
//##} if(m_recv_Buffer.Length < pkg_head_tmp.length){
Debug.Log("## TOBE Continue:还需要接受"+(pkg_head_tmp.length-m_recv_Buffer.Length)+"个字节 ");
Receive(pkg_head_tmp.length - m_recv_Buffer.Length, false, m_recv_Buffer);
return ;
}else if(m_recv_Buffer.Length == pkg_head_tmp.length){
Debug.Log("## 刚刚好接受完一个包数据,进行处理...[pkg_head_tmp.length="+pkg_head_tmp.length+"]");
m_CallReceive(true, error_Socket, "", m_recv_Buffer, "");
}else{
Debug.LogError("========ERROR=================");
Debug.LogError(" 多接受了"+(pkg_head_tmp.length-m_recv_Buffer.Length)+"个字节!!!!!!! ");
Debug.LogError("========ERROR=================");
return;
}
#endregion
}
//结束异步的数据读取之后,从新开始接收数据
Receive(, true, null);
}
catch (System.Exception ex)
{
if (null != m_CallReceive)
{
m_CallReceive(false, Error_Socket.RECEIV_UNSUCCESS_UNKNOW, ex.ToString(), null, "");
Debug.Log(ex.ToString());
}
}
} //定义Object
private class StateObject
{
internal byte[] sBuffer;//本次接收到的实际数据
internal Socket sSocket;//socket
internal bool spkgTag;//包的标示
internal byte[] sheadBuffer;//消息头的数据
internal StateObject(int size, Socket sock, bool tag, byte[] data)
{
sheadBuffer = data;
sBuffer = new byte[size];
sSocket = sock;
spkgTag = tag;
}
}
最主要的还是 如果数据不够的话,要继续接受。以上代码 是公司框架之后的代码,是游戏代码的一部分,只供学习逻辑,不可以直接运行!
这是我自己的逻辑。
其实还有另外一种逻辑,那就是 使劲接受到一个比较大的缓冲区。接受的足够了,在处理,其他的继续接受。
【手机网络游戏 编程】C#异步socketAPI调用 处理数据的流程的更多相关文章
- 【憩园】C#并发编程之异步编程(一)
写在前面 C#5.0中,对异步编程进行了一次革命性的重构,引入了async和await这两个关键字,使得开发人员在不需要深刻了解异步编程的底层原理,就可以写出十分优美而又代码量极少的代码.如果使用得当 ...
- Java网络编程中异步编程的理解
目录 前言 一.异步,同步,阻塞和非阻塞的理解 二.异步编程从用户层面和框架层面不同角度的理解 用户角度的理解 框架角度的理解 三.为什么使用异步 四.理解这些能在实际中的应用 六.困惑 参考文章 前 ...
- C#复习笔记(5)--C#5:简化的异步编程(异步编程的基础知识)
异步编程的基础知识 C#5推出的async和await关键字使异步编程从表面上来说变得简单了许多,我们只需要了解不多的知识就可以编写出有效的异步代码. 在介绍async和await之前,先介绍一些基础 ...
- Windows系统编程之异步I/O和完成端口
Windows系统编程之异步I/O和完成端口[作者]北极星2003[来源]看雪技术论坛(bbs.pediy.com) [时间]2006年7月1日 一. 同步I/O和异步I/O 在介绍这部分内容之前先 ...
- .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)
本文内容 异步编程类型 异步编程模型(APM) 参考资料 首先澄清,异步编程模式(Asynchronous Programming Patterns)与异步编程模型(Asynchronous Prog ...
- C#并发编程之异步编程2
C#并发编程之异步编程(二) 写在前面 前面一篇文章介绍了异步编程的基本内容,同时也简要说明了async和await的一些用法.本篇文章将对async和await这两个关键字进行深入探讨,研究其中 ...
- 从执行上下文角度重新理解.NET(Core)的多线程编程[1]:基于调用链的”参数”传递
线程是操作系统能够进行运算调度的最小单位,操作系统线程进一步被封装成托管的Thread对象,手工创建并管理Thread对象已经成为了所能做到的对线程最细粒度的控制了.后来我们有了ThreadPool, ...
- 进程内部异步事件调用组件Async-Event
项目坐标:https://github.com/cncduLee/async-event async-event 进程内部异步事件调用组件 解决什么问题: 加速服务处理效率.提供进程级别的事件发布和异 ...
- Matlab.NET混合编程技巧之——直接调用Matlab内置函数(附源码)
原文:[原创]Matlab.NET混合编程技巧之--直接调用Matlab内置函数(附源码) 在我的上一篇文章[原创]Matlab.NET混编技巧之——找出Matlab内置函数中,已经大概的介绍了mat ...
随机推荐
- 001.NFS简介
一 简介 NFS 是Network File System的缩写,即网络文件系统.一种使用于分散式文件系统的协定,由Sun公司开发,于1984年向外公布.功能是通过网络让不同的机器.不同的操作系统能够 ...
- C#并行编程(6):线程同步面面观
理解线程同步 线程的数据访问 在并行(多线程)环境中,不可避免地会存在多个线程同时访问某个数据的情况.多个线程对共享数据的访问有下面3种情形: 多个线程同时读取数据: 单个线程更新数据,此时其他线程读 ...
- 2019 A类
- Nessus漏洞扫描教程之安装Nessus工具
Nessus漏洞扫描教程之安装Nessus工具 Nessus基础知识 Nessus号称是世界上最流行的漏洞扫描程序,全世界有超过75000个组织在使用它.该工具提供完整的电脑漏洞扫描服务,并随时更新其 ...
- 用C语言的rand()和srand()产生伪随机数的方法总结
标准库<cstdlib>(被包含于<iostream>中)提供两个帮助生成伪随机数的函数: 函数一:int rand(void):从srand (seed)中指定的seed开始 ...
- BZOJ.1003.[ZJOI2006]物流运输(DP 最短路Dijkstra)
题目链接 容易看出是个最短路+DP.既然答案和天数有关,那么就令\(f[i]\)表示前\(i\)天最小成本. 这个转移很好想: \(f[i]=\min(f[i],\ f[j]+cost(j+1,i)+ ...
- BZOJ.1143.[CTSC2008]祭祀(Dilworth定理 最大流ISAP)
题目链接 题目是求最长反链,反链指点集内任意两点不能互相到达. 根据Dilworth定理,在DAG中,\[最长反链 = 最小路径覆盖 = V - 最大匹配数\] 用Floyd求一遍传递闭包后,在所有可 ...
- 关于Android4.X的Alertdialog对话框
最近在做Android4.0的开发,发现AlertDialog相比较以前有了较大变化,就是在触摸对话框边缘外部,对话框消失 于是研究其父类发现,可以设置这么一条属性,当然必须先AlertDialog. ...
- BZOJ 3245: 最快路线 spfa
3245: 最快路线 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=3245 Description 精明的小R每每开车出行总是喜欢走最快 ...
- Java调用OCR进行图片识别
使用Java语言,通过Tesseract-OCR对图片进行识别. 1.Tesseract-OCR 下载windows版本并安装. 2.程序如下: a.ImageIOHelper类 package OC ...