111,119
社区成员
发帖
与我相关
我的任务
分享
while (m_Reader.DataAvailable || currentSize < packSize)
{
readSize = m_Reader.Read(bytes, 0, (int)m_ConnectSocket.ReceiveBufferSize);
if (readSize > 0)
{
currentSize += readSize;//读取成功,进行叠加
totalBytes = totalBytes.Concat(bytes).ToArray();//将读取的内容添加到容器后面
}
}
其中这一段是有问题的,我将数据串起来采用的是 byte.Concat方法,而该方法是将bytes添加到totalBytes后面。
bytes长度为1024。这代码在单机或网络环境好的情况是可以使用的,也是网上搜索给出的代码标准答案。
但是如果在网络没那么好的情况下,是有问题的。
Networkstream的Read方法是尽可能的往stream里面读取数据。如果网络不好的情况下,真实有用的数据可能只有512,但是Read中强行读取1024,导致bytes前512个数据是有用数据,而后面的512~1024数据则是之前的数据。
而我的代码中直接把1024的bytes添加到结果后面,这样是不正确的。
解决办法是类似下面的代码一样
if (readSize > 0)
{
LogRecord.WriteLog(readSize);
currentSize += readSize;
byte[] temp = new byte[readSize];
Array.Copy(bytes, 0, temp, 0, readSize);
totalBytes = totalBytes.Concat(temp).ToArray();//C#神器,byte[]会自动延长
}
多谢xian_wwq指出应该打印到日志内。项目中引用Log4Net将结果打到文件里面比对一下就发现问题了。
至于zanfeng指出Networkstream并不可靠,但我并不知道改用什么其他方法接收。
以及chengbin0602指出的要异步接收。
结贴给分,感谢各位!
花时间看了,没有帮助+1
11楼开始我就回复贴代码,并阐述我的问题
没人回么,自己Up~
谢谢指出问题,不过逻辑完善后,这代码在外网的情况下依然不能接收全数据。。。数据读到的长度是跟我想的一样,但是数据内容不一样[/quote]
首先说c#提供的类没有这个bug。
要找到问题,建议你先不处理数据,Server侧只接收数据。
调试通讯程序,加断点的方法不靠谱,原因我不解释了
在client发送数据和Server接收数据的地方打印日志。
通过日志帮助找问题点。

这位兄弟所言甚是,那么能不能提供一些异步的示例给小弟参考呢?
谢谢指出问题,不过逻辑完善后,这代码在外网的情况下依然不能接收全数据。。。数据读到的长度是跟我想的一样,但是数据内容不一样
public static ManualResetEvent allDone = new ManualResetEvent(false);
private static byte[] bytes = new byte[m_ConnectSocket.ReceiveBufferSize];
private static byte[] totalBytes = new byte[0];//C#神器,byte[]会自动延长
public class State
{
public NetworkStream ns;
public byte[] buffer;
public byte[] result;
}
public static void myReadCallBack(IAsyncResult iar)
{
State state = (State)iar.AsyncState;
NetworkStream myNetworkStream = state.ns;
int numberOfBytesRead;
numberOfBytesRead = myNetworkStream.EndRead(iar);
if (numberOfBytesRead > 0)
{
totalBytes = totalBytes.Concat(state.buffer).ToArray();
//接收到的消息长度可能大于缓冲区总大小,反复循环直到读完为止
while (myNetworkStream.DataAvailable)
{
myNetworkStream.BeginRead(state.buffer, 0, state.buffer.Length, new AsyncCallback(myReadCallBack), state);
}
}
else
{
//执行这里我认为数据已经全部接收完毕
//开始执行如11楼的处理数据代码
//也就是从 state.buffer 中取出包头判断是否我的包
//然后提取数据长度,根据数据长度提取数据,将数据交由数据处理线程进行处理
allDone.Set();
}
}
//线程接收代码如下
while (m_Reader.DataAvailable)
{
State state = new State();
state.ns = m_Reader;
state.buffer = new byte[m_ConnectSocket.ReceiveBufferSize]; ;
state.result = new byte[0];
totalBytes = new byte[0];
m_Reader.BeginRead(state.buffer, 0, state.buffer.Length, myReadCallBack, state);
allDone.WaitOne();
}
使用异步的BeginRead,但是代码没有实现我想要的结果。其实对于BeginRead很混乱,希望各位大牛能帮我理清思路。
因为网上关于BeginRead的代码真是惨不忍睹,全是代码片段,全是无脑复制,好一点的在网络环境好的情况下还能接收成功。
但更多的根本没用