之前客户端在网络条件好的时候,运行没问题.但是有时候手机的网络不稳定,接受数据可能不稳定,导致接受数据错误,一直都不知道,原来是接受数据处理的不够好!

现在更改过后的接受数据的逻辑如下:

    //接收
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调用 处理数据的流程的更多相关文章

  1. 【憩园】C#并发编程之异步编程(一)

    写在前面 C#5.0中,对异步编程进行了一次革命性的重构,引入了async和await这两个关键字,使得开发人员在不需要深刻了解异步编程的底层原理,就可以写出十分优美而又代码量极少的代码.如果使用得当 ...

  2. Java网络编程中异步编程的理解

    目录 前言 一.异步,同步,阻塞和非阻塞的理解 二.异步编程从用户层面和框架层面不同角度的理解 用户角度的理解 框架角度的理解 三.为什么使用异步 四.理解这些能在实际中的应用 六.困惑 参考文章 前 ...

  3. C#复习笔记(5)--C#5:简化的异步编程(异步编程的基础知识)

    异步编程的基础知识 C#5推出的async和await关键字使异步编程从表面上来说变得简单了许多,我们只需要了解不多的知识就可以编写出有效的异步代码. 在介绍async和await之前,先介绍一些基础 ...

  4. Windows系统编程之异步I/O和完成端口

    Windows系统编程之异步I/O和完成端口[作者]北极星2003[来源]看雪技术论坛(bbs.pediy.com) [时间]2006年7月1日 一.  同步I/O和异步I/O 在介绍这部分内容之前先 ...

  5. .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)

    本文内容 异步编程类型 异步编程模型(APM) 参考资料 首先澄清,异步编程模式(Asynchronous Programming Patterns)与异步编程模型(Asynchronous Prog ...

  6. C#并发编程之异步编程2

    C#并发编程之异步编程(二)   写在前面 前面一篇文章介绍了异步编程的基本内容,同时也简要说明了async和await的一些用法.本篇文章将对async和await这两个关键字进行深入探讨,研究其中 ...

  7. 从执行上下文角度重新理解.NET(Core)的多线程编程[1]:基于调用链的”参数”传递

    线程是操作系统能够进行运算调度的最小单位,操作系统线程进一步被封装成托管的Thread对象,手工创建并管理Thread对象已经成为了所能做到的对线程最细粒度的控制了.后来我们有了ThreadPool, ...

  8. 进程内部异步事件调用组件Async-Event

    项目坐标:https://github.com/cncduLee/async-event async-event 进程内部异步事件调用组件 解决什么问题: 加速服务处理效率.提供进程级别的事件发布和异 ...

  9. Matlab.NET混合编程技巧之——直接调用Matlab内置函数(附源码)

    原文:[原创]Matlab.NET混合编程技巧之--直接调用Matlab内置函数(附源码) 在我的上一篇文章[原创]Matlab.NET混编技巧之——找出Matlab内置函数中,已经大概的介绍了mat ...

随机推荐

  1. Ansible专题整理

    Ansible 专题文章总览 Ansible小手册,仅供参考 文章如未明确说明实验环境,默认如下: OS:Centos 6.7 x86_64 Ansible: 2.1.2.0 Python: 2.6. ...

  2. 009.MySQL-Keepalived搭配脚本03

    vim /etc/keepalived/check_MySQL.sh #vim #!/bin/bash MYSQL=/usr/local/mysql/bin/mysql MYSQL_HOST=loca ...

  3. webpack1.x环境配置与打包基础【附带各种 "坑" 与解决方案!持续更新中...】

    首先介绍传统模块化开发的主流方案: 1.基与CMD的sea.js,玉伯提出的解决方案,据说原来京东团队在使用.用时才定义,就近加载. 2.基于AMD的require.js,之前在用.提前声明与定义.国 ...

  4. Wireshark数据抓包教程之Wireshark的基础知识

    Wireshark数据抓包教程之Wireshark的基础知识 Wireshark的基础知识 在这个网络信息时代里,计算机安全始终是一个让人揪心的问题,网络安全则有过之而无不及.Wireshark作为国 ...

  5. CodeForces 794 G.Replace All

    CodeForces 794 G.Replace All 解题思路 首先如果字符串 \(A, B\) 没有匹配,那么二元组 \((S, T)\) 合法的一个必要条件是存在正整数对 \((x,y)\), ...

  6. 五校联考R1 Day1T3 平面图planar(递推 矩阵快速幂)

    题目链接 我们可以把棱柱拆成有\(n\)条高的矩形,尝试递推. 在计算的过程中,第\(i\)列(\(i\neq n\))只与\(i-1\)列有关,称\(i-1\)列的上面/下面为左上/左下,第\(i\ ...

  7. [转]Twemproxy 介绍与使用

    Twemproxy是一种代理分片机制,由Twitter开源.Twemproxy作为代理,可接受来自多个程序的访问,按照路由规则,转发给后台的各个Redis服务器,再原路返回.该方案很好的解决了单个Re ...

  8. Snmp学习总结(五)——WindowsServer2008安装和配置SNMP

    一.安装SNMP 在Windows Server 2008以及Windows Server 2008 R2中,SNMP是以一个服务器功能的形式存在的,SNMP的安装步骤如下所示: 1.打开[开始]→[ ...

  9. 面试题07_用两个栈实现队列——剑指offer系列

    题目描写叙述: 用两个栈实现一个队列. 队列的声明例如以下,请实现它的两个函数appendTail 和 deleteHead.分别完毕在队列尾部插入结点和在队列头部删除结点的功能. 解题思路: 栈的特 ...

  10. C#编程(二十九)----------泛型接口

    泛型接口 定义 先来看一个简单的例子: public class Sharp {} public class Rectangle:Sharp {} 上面定义了两个简单的类,一个是图形类,一个是矩形类; ...