使用UDP向局域网内计算机发送广播消息,并传递以下这个结构体:
public struct Astruct
{
public int seq;
public char[] name;
public ulong len;
public char[] data;
}
Astruct ast=new Astruct();
怎样用代码实现呢?
序列化的方法试了不行,UDP似乎不能接收网络传递过来的流,NetworkStream不适用于无连接的协议。
通过指针转换的办法,在C++里可以使用char* buffer=(char*)ast,但在C#里不行,不知道怎样把结构体转化为byte[]进行传递。
或者有没有别的办法实现在局域网中广播结构体~
public struct Astruct
{
public int seq;
public char[] name;
public ulong len;
public char[] data;
}
Astruct ast=new Astruct();
怎样用代码实现呢?
序列化的方法试了不行,UDP似乎不能接收网络传递过来的流,NetworkStream不适用于无连接的协议。
通过指针转换的办法,在C++里可以使用char* buffer=(char*)ast,但在C#里不行,不知道怎样把结构体转化为byte[]进行传递。
或者有没有别的办法实现在局域网中广播结构体~
xs.Serialize(stream, ast);
如果不是同一个程序,甚至都不是.NET的话自已用BinaryWriter BinaryReader来搞吧
Astruct加一个方法,或只读属性 public byte[] GetRawData()或RawData
里面用BinaryWriter把结构内的值按一定顺序写进去
结构用一个构造函数public Astruct(byte[] data);里面用BinaryReader读取,怎么读取处你写入的顺序有关简单类型int,ulong与byte的转换可以BitConverter类来操作,更方便,至于char[]类型可以随便选个Encoding来搞定,还原的时候用同样的Encoding就行了。或者直接把一个char转成两个字节写进去。
如果不是,可以用2楼的XmlSerializer(长度较长)或BinaryFormatter(比较精简)系列化成byte数组。传输以后再转回来。using System.Runtime.Serialization.Formatters.Binary;
//...
[Serializable]
public struct Astruct
{
public int seq;
public char[] name;
public ulong len;
public char[] data; public byte[] GetSerializedBytes()
{
BinaryFormatter bf = new BinaryFormatter(); //<---
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
bf.Serialize(ms, this); //<---系列化成byte数组
ms.Seek(0, System.IO.SeekOrigin.Begin);
return ms.ToArray();
}
}
public static Astruct FromSerilizedBytes(byte[] data)
{
BinaryFormatter bf = new BinaryFormatter();
using (System.IO.MemoryStream ms = new System.IO.MemoryStream(data))
{
return (Astruct)bf.Deserialize( ms ); //<---从byte数组再转回来
}
}
}
IPEndPoint iep1 = new IPEndPoint(IPAddress.Broadcast, 9050);
BinaryFormatter bf;
bf = new BinaryFormatter();
MemoryStream stream = new MemoryStream();
Astruct ast = new Astruct();
ast.seq = 4;
ast.name = new char[] { 'n', 'a', 'm', 'e' };
ast.len = 4;
ast.data = new char[] { 'd', 'a', 't', 'a' };
bf.Serialize(stream, ast);
byte[] buff = stream.ToArray();
sock.SendTo(buff, iep1);
接收端:Socket sock = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
IPEndPoint iep = new IPEndPoint(IPAddress.Any, 9050);
sock.Bind(iep);
EndPoint ep = (EndPoint)iep;
NetworkStream stream = new NetworkStream(sock);//取得服务端发送的数据(无论用哪种类型都无法接收到网络的流)
BinaryFormatter bf;
bf = new BinaryFormatter();
Astruct reci = (Astruct)bf.Deserialize(stream);//反序列化数据
Console.Write("name is :");
Console.WriteLine(reci.name);
Console.WriteLine("seq is :" + reci.seq);
Console.WriteLine("len is :" + reci.len);
Console.Write("data is :");
目前的主要问题出在如何能够发送和接收到。接收端现在能编译通过,但只要运行就会有异常。不知道该怎样做才能有效获取到网络中的数据流。解析是后面的事了。刚看到7楼给了个例程,我一会儿试一下。
看样子你的问题主要不在序列化上面
UDP只能用Send / Receive,
NetworkStream是用在TCP上的另外建议你用TCPClient/UDPClient,这两个都是在Socket上的封装
我也觉得我的主要问题不是序列化,我是想知道怎么接收,如果不用NetworkStream该用什么呢?
TCPClient/UDPClient的功能用socket不是也可以实现吗?我就是这样用的。为什么建议我用那两个呢?
UDP怎样用Send和Receive接收结构体序列化后产生的流呢?应该不能像普通的字节流那样发送和接收吧?
发送端:
string hostname = Dns.GetHostName();
byte[] data = Encoding.ASCII.GetBytes(hostname);
IPEndPoint iep1 = new IPEndPoint(IPAddress.Broadcast, 9050);
sock.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.Broadcast, 1);
sock.SendTo(data, iep1);
接收端:
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint iep = new IPEndPoint(IPAddress.Any, 9050);
sock.Bind(iep);
EndPoint ep = (EndPoint)iep;
byte[] data = new byte[1024];
int recv = sock.ReceiveFrom(data, ref ep);
string stringData = Encoding.ASCII.GetString(data, 0, recv);
Console.WriteLine("received: {0} from: {1}",stringData, ep.ToString());在这段上面怎么改造呢?把结构体序列化过后。
说明一下我的修改方法:
修改的内容有:
1.从发送端到接收端的byte[]接收长度改变了,因此应该获取传过来的参数的长度,并修改为合适。
2.出现过一个cast的问题,好像是说结构序列化以后还是对象,不能转换为值类型,所以修改成类。
3.虽然在send和receive端定义了两个一摸一样的结构,但是系统还是认为是不同的,所以将公共类型定义独立出来建了一个工程。
4.send和receive的各自的解决方案均要添加已存在的工程comm,然后添加引用到那个工程里。
谢谢上面的各位~~!
散分啦~