关于TCPclient发送和接收数据的问题。希望大家帮忙,谢谢

satan_dongdong 2008-12-26 04:47:02
我的代码如下:

需要发送的数据为message中的内容,下面是将message序列化,然后写入NetworkStream

private NetworkStream ntStream;
//
//
//发送数据到
public static void Send()
{
ArrayList message = new ArrayList();
message.Add("test0");
message.Add("test1");
//
// 序列化要传送的数据到临时流
//
MemoryStream mStream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
formatter.TypeFormat = FormatterTypeStyle.TypesWhenNeeded;
formatter.Serialize(mStream, message);
mStream.Flush();
//
// 写入流头
//
MemoryStream sendStream = new MemoryStream();
Byte[] buffer;
//
// 写验证标识 (1 字节)
//
buffer = BitConverter.GetBytes(isValidate);
sendStream.Write(buffer, 0, buffer.Length);
//
// 写临时流长度 (4 字节)
//
buffer = BitConverter.GetBytes((int) mStream.Length);
sendStream.Write(buffer, 0, buffer.Length);
//
// 写发送标识 (4 字节)
//
buffer = BitConverter.GetBytes(StreamID ++);
sendStream.Write(buffer, 0, buffer.Length);
//
// 写入临时流到发送流
//
Byte[] mbuffer = mStream.GetBuffer();
sendStream.Write(mbuffer, 0, (int) mStream.Length);
sendStream.Flush();

Byte[] sendBytes = sendStream.GetBuffer();
ntStream.Write(sendBytes, 0, (int) sendStream.Length);
}

以下代码为读出NetworkStream,在收到NetworkStream后,将其反序列化:
//
//将接收到的信息进行再分配处理
//
public static ArrayList ReceiveScheduler(TcpClient client, NetworkStream stream)
{
byte[] bytes = new byte[client.ReceiveBufferSize];
ArrayList message = null;

int bytesRead = stream.Read(bytes, 0, (int) client.ReceiveBufferSize); // 提示这行出错。

if (bytesRead > 0)// 图过信息队列中,信息内容不为空,则读出
{
try
{
int sendLength = BitConverter.ToInt32(bytes, 1) + 9;

if (sendLength == bytesRead)
{
MemoryStream mStream = new MemoryStream(bytes, 9, sendLength - 9);
BinaryFormatter formatter = new BinaryFormatter();
formatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
formatter.TypeFormat = FormatterTypeStyle.TypesWhenNeeded;
message = (ArrayList) formatter.Deserialize(mStream);
message.Add(BitConverter.ToUInt32(bytes, 5));
}
}
catch
{
//
// 忽略
//
}
}

return message;
}

遇到的问题:
message的类型为ArrayList,其中的内容message[0]为:test0;message[1]为:test1;将message序列化后写入NetworkStream发送,在接收到NetworkStream后将其反序列化,发现得到的message的内容与原来的内容不符合,请问各位,是不是我上面的代码在什么地方出错了呢?请帮忙看看,谢谢大家
...全文
1407 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
kenesyu 2009-01-06
  • 打赏
  • 举报
回复
帮楼主顶起!我也要学习
satan_dongdong 2009-01-06
  • 打赏
  • 举报
回复
顶起
satan_dongdong 2009-01-05
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 fengyecsdn 的回复:]
先用固定缓冲大小 来检查代码的收发是否正常
比如 使用 2048字节收发。。

然后改用变长。 检查你的读写长度。
[/Quote]

试过,也是会变的
fengyecsdn 2009-01-05
  • 打赏
  • 举报
回复
先用固定缓冲大小 来检查代码的收发是否正常
比如 使用 2048字节收发。。

然后改用变长。 检查你的读写长度。
satan_dongdong 2009-01-04
  • 打赏
  • 举报
回复
顶起
satan_dongdong 2009-01-03
  • 打赏
  • 举报
回复
以下摘自MSDN:

GetBuffer()

返回从其创建此流的无符号字节数组。

[C#]
public virtual byte[] GetBuffer();

返回值
创建此流所用的字节数组;或者如果在当前实例的构造期间没有向 MemoryStream 构造函数提供字节数组,则为基础数组。


ToArray()
将整个流内容写入字节数组,而与 Position 属性无关。

[C#]
public virtual byte[] ToArray();

返回值
新字节数组。





satan_dongdong 2008-12-31
  • 打赏
  • 举报
回复
顶一下
wo789 2008-12-31
  • 打赏
  • 举报
回复
请不要用 mStream.GetBuffer(), 把它替换为mStream.ToArray()。
因为mStream.GetBuffer()并不是获取的整个内存流的数据,而是内部缓冲区的数据。
satan_dongdong 2008-12-30
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 bingzhuyue 的回复:]
以前出现过,后来解决了,每次发送的字节大一些.
[/Quote]

每次发送的字节大一些???能具体说说吗?谢谢
satan_dongdong 2008-12-30
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 xjh_net 的回复:]
string myStr1 = "aaaaaaa";
Send(myStr1);

byte[] bytes = new byte[10240];
int bytesRead = ntGameServerManagerStream.Read(bytes,0,myTCPclient.ReceiveBufferSize);
ReceiveScheduler(myTCPclient, ntStream);

string myStr2 = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
Send(myStr2);
int bytesRead2 = ntGameS…
[/Quote]

还是一样,没什么改变的
xjh_net 2008-12-30
  • 打赏
  • 举报
回复
string myStr1 = "aaaaaaa";
Send(myStr1);

byte[] bytes = new byte[10240];
int bytesRead = ntGameServerManagerStream.Read(bytes,0,myTCPclient.ReceiveBufferSize);
ReceiveScheduler(myTCPclient, ntStream);

string myStr2 = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
Send(myStr2);
int bytesRead2 = ntGameServerManagerStream.Read(bytes,0,myTCPclient.ReceiveBufferSize);
这样测下,看接收的大小还一样吗?按理说不一样。
bbbbbb888888 2008-12-30
  • 打赏
  • 举报
回复
直接发送byte[]不行么?
bingzhuyue 2008-12-30
  • 打赏
  • 举报
回复
以前出现过,后来解决了,每次发送的字节大一些.
xu_2007 2008-12-29
  • 打赏
  • 举报
回复
在服务器端发送数据的代码下面加一行暂停线程多少秒的函数(SELLP函数),一般暂停200毫秒左右!
satan_dongdong 2008-12-29
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 yagebu1983 的回复:]
你把ArrayList的内容弄成实体对象试试!!
[/Quote]


不好意思,请问具体怎么弄呢?谢谢
yagebu1983 2008-12-29
  • 打赏
  • 举报
回复
你把ArrayList的内容弄成实体对象试试!!
satan_dongdong 2008-12-29
  • 打赏
  • 举报
回复
需要发送的数据为message中的内容,下面是将message序列化,然后写入NetworkStream

private NetworkStream ntStream;
private TcpClient myTCPclient;
//
//
//发送数据到
public static void Send(string myStr)
{
ArrayList message = new ArrayList();
message.Add(myStr);
//
// 序列化要传送的数据到临时流
//
MemoryStream mStream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
formatter.TypeFormat = FormatterTypeStyle.TypesWhenNeeded;
formatter.Serialize(mStream, message);
mStream.Flush();
//
// 写入流头
//
MemoryStream sendStream = new MemoryStream();
Byte[] buffer;
//
// 写验证标识 (1 字节)
//
buffer = BitConverter.GetBytes(isValidate);
sendStream.Write(buffer, 0, buffer.Length);
//
// 写临时流长度 (4 字节)
//
buffer = BitConverter.GetBytes((int) mStream.Length);
sendStream.Write(buffer, 0, buffer.Length);
//
// 写发送标识 (4 字节)
//
buffer = BitConverter.GetBytes(StreamID ++);
sendStream.Write(buffer, 0, buffer.Length);
//
// 写入临时流到发送流
//
Byte[] mbuffer = mStream.GetBuffer();
sendStream.Write(mbuffer, 0, (int) mStream.Length);
sendStream.Flush();

Byte[] sendBytes = sendStream.GetBuffer();
ntStream.Write(sendBytes, 0, (int) sendStream.Length);
}

以下代码为读出NetworkStream,在收到NetworkStream后,将其反序列化:
//
//将接收到的信息进行再分配处理
//
public static ArrayList ReceiveScheduler(TcpClient client, NetworkStream stream)
{
byte[] bytes = new byte[client.ReceiveBufferSize];
ArrayList message = null;

int bytesRead = stream.Read(bytes, 0, (int) client.ReceiveBufferSize); // 提示这行出错。

if (bytesRead > 0)// 图过信息队列中,信息内容不为空,则读出
{
try
{
int sendLength = BitConverter.ToInt32(bytes, 1) + 9;

if (sendLength == bytesRead)
{
MemoryStream mStream = new MemoryStream(bytes, 9, sendLength - 9);
BinaryFormatter formatter = new BinaryFormatter();
formatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
formatter.TypeFormat = FormatterTypeStyle.TypesWhenNeeded;
message = (ArrayList) formatter.Deserialize(mStream);
message.Add(BitConverter.ToUInt32(bytes, 5));
}
}
catch
{
//
// 忽略
//
}
}

return message;
}

/////////////////////////////
用的时候
private void button1_Click(object sender, System.EventArgs e)
{
string myStr1 = "aaaaaaa";
Send(myStr1);

// 测试用,第一次断点时,放在此处;第二次断点时放再 Send(myStr2)后面;发现两次的 bytesRead 值都一样
byte[] bytes = new byte[myTCPclient.ReceiveBufferSize];
int bytesRead = ntGameServerManagerStream.Read(bytes,0,myTCPclient.ReceiveBufferSize);

ReceiveScheduler(myTCPclient, ntStream);

string myStr2 = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
Send(myStr2);
}
首先将 myStr1 写入ntStream ,然后用函数 ReceiveScheduler(myTCPclient, ntStream)ntStream 读出;然后再向 ntStream 写入 myStr2 ;运行的时候断点发现,两次 bytesRead 的值都是一样的,是不是我第二次写入ntStream的时候没有成功呢?这是什么原因呢?麻烦大家帮忙看看,非常感谢。
homejiji 2008-12-29
  • 打赏
  • 举报
回复
汗。。粘包。。。
方法(如果数据较大可以分包发送),给发送的数据包加上头信息,一般我喜欢设的顺序是包长,包个数,第几个包等等。。。
具体的方法你可以去网上查找一下tcpip通讯的分包组包
xu_2007 2008-12-28
  • 打赏
  • 举报
回复
很有可能是粘包现象
satan_dongdong 2008-12-28
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 xu_2007 的回复:]
很有可能是粘包现象
[/Quote]


请问是什么原因造成的呢?我应该如何解决呢?谢谢
加载更多回复(6)

111,130

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧