求助.C#客户端和服务端之间通信乱码

Xillscar 2012-05-22 11:34:17
C# 利用结构体服务端和客户端之间交互.中文部分客户端发送出去正常.到服务端接收之后解析出来是乱码.但是在把解析出来的乱码返回给客户端.客户单接收后又正常.请各位高手给予帮助解答.所有脚本都是utf8格式
以下为结构体代码 服务端和客户端都一样


namespace GameData
{
[StructLayout(LayoutKind.Sequential, Pack = 1,CharSet = CharSet.Unicode), Serializable]

public struct Loginmsg
{
public byte datatypes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string userid;
}
}


客户端发送部分代码



if(message[0]==1)
{
Loginmsg msg=new Loginmsg();
msg.datatype=1;
msg.userid="我爱你";
byte[] bytes=Tool.StructToBytes(msg);
BinaryWriter bw = new BinaryWriter(networkStream);
short count = (short)bytes.Length;
bw.Write(count);
bw.Write(bytes);
bw.Flush();
}

服务端接收部分代码

if (receiveMessage[0] == 1)
{
Loginmsg ms = new Loginmsg();
ms = (Loginmsg)Tool.BytesToStruct(receiveMessage, ms.GetType());
Console.WriteLine(ms.userid);
}



Tool工具代码

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;

namespace GameData
{
public class Tool
{
public static byte[] StructToBytes(object obj)
{
int size = Marshal.SizeOf(obj);
byte[] bytes = new byte[size];
IntPtr structPtr = Marshal.AllocHGlobal(size); //分配结构体大小的内存空间
Marshal.StructureToPtr(obj, structPtr, false); //将结构体拷到分配好的内存空间
Marshal.Copy(structPtr, bytes, 0, size); //从内存空间拷到byte数组
Marshal.FreeHGlobal(structPtr); //释放内存空间
return bytes;
}

public static object BytesToStruct(byte[] bytes, Type type)
{
int size = Marshal.SizeOf(type);
if (size > bytes.Length)
return null;
IntPtr structPtr = Marshal.AllocHGlobal(size); //分配结构大小的内存空间
Marshal.Copy(bytes, 0, structPtr, size); //将byte数组拷到分配好的内存空间
object obj = Marshal.PtrToStructure(structPtr, type);
Marshal.FreeHGlobal(structPtr);
return obj;
}
}
}


...全文
221 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
Xillscar 2012-05-22
  • 打赏
  • 举报
回复
client 是一个TCP连接 连接的是服务端
Xillscar 2012-05-22
  • 打赏
  • 举报
回复
MemoryStream 不认 client.GetStream();

所以还得用另外的办法把 client.GetStream();加入到 MemoryStream 中发送才正常
Xillscar 2012-05-22
  • 打赏
  • 举报
回复
networkStream 是 NetworkStream

networkStream = client.GetStream();
bdmh 2012-05-22
  • 打赏
  • 举报
回复
我用如下代码进行测试,不知道你的networkStream是什么,这里用MemoryStream代替

Loginmsg msg = new Loginmsg();
msg.datatypes = 1;
msg.userid = "我爱你";
byte[] bytes = Tool.StructToBytes(msg); //bytes长度35字节
MemoryStream networkStream = new MemoryStream();
BinaryWriter bw = new BinaryWriter(networkStream);
short count = (short)bytes.Length;
bw.Write(count);
bw.Write(bytes);
bw.Flush();
//这里说明一下,如果直接传给服务端bytes是没有问题的,但是如果用MemoryStream传递,就需要先转为字节数组
bytes = new byte[networkStream.Length];//此时长度为37,不是35了
networkStream.Read(bytes, 0, bytes.Length);
Loginmsg ms = new Loginmsg();
ms = (Loginmsg)Tool.BytesToStruct(bytes, ms.GetType());//这里返回结果异常
test2050 2012-05-22
  • 打赏
  • 举报
回复
编译通不过那是代码没写对。找找MemoryStream的例子代码
Xillscar 2012-05-22
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

引用 4 楼 的回复:
兄弟 我这个是在TCP网络环境下的交互.直接用内存流..不行的

就是在tcp,我就是这么用的, BinaryWriter 的存储和 MemoryStream有区别的,特别是对string类型这样飞固定长度的字段
[/Quote]

恩这个我认同.但是我这边在用MemoryStream 处理的时候程序编译都无法通过..
bdmh 2012-05-22
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]
兄弟 我这个是在TCP网络环境下的交互.直接用内存流..不行的
[/Quote]
就是在tcp,我就是这么用的, BinaryWriter 的存储和 MemoryStream有区别的,特别是对string类型这样飞固定长度的字段
Xillscar 2012-05-22
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

用MemoryStream换掉 BinaryWriter 试试
[/Quote]

兄弟 我这个是在TCP网络环境下的交互.直接用内存流..不行的
Xillscar 2012-05-22
  • 打赏
  • 举报
回复
使用Encoding类编码下。 这个已经尝试过 依然是乱码
devmiao 2012-05-22
  • 打赏
  • 举报
回复
使用Encoding类编码下。
bdmh 2012-05-22
  • 打赏
  • 举报
回复
用MemoryStream换掉 BinaryWriter 试试
Xillscar 2012-05-22
  • 打赏
  • 举报
回复
感谢大家帮助.问题已经解决
出错的地方是结构体文件
bdmh 2012-05-22
  • 打赏
  • 举报
回复
找到问题了,看下面两句

bw.Write(count);
bw.Write(bytes);
注意你读写了count这个变量,这样多出来2个字节,你在BytesToStruct时,没有考虑这个多出的字节,这样转为Loginmsg类型时,位置就不对了,bytes中是Loginmsg的类型,你需要先越过2个字节,再转换

111,126

社区成员

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

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

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