UDP通信,如何实现不停的接收数据

zhangshuqiang123 2011-03-08 10:18:30
服务器端发送数据代码:
                    IPAddress broadcast = IPAddress.Parse(ip);
IPEndPoint ep = new IPEndPoint(broadcast, ipPort);
udpClent.Connect(ep);

byte[] sendData = getSendData(data, dateTime);
sendData[1] = des;
udpClent.Send(sendData, 35);
byte[] temp = new byte[10] { 0x7F, 0x01, 0xE1, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
temp[1] = des;
getBCD(dateTime).CopyTo(temp, 5);
udpClent.Send(temp, 10);

客户端接收代码

private void reciveButton_Click(object sender, EventArgs e)
{
try
{
IPEndPoint ep = new IPEndPoint(IPAddress.Any, int.Parse(textPort.Text));
UdpClient client = new UdpClient(ep);
UdpState state = new UdpState();
state.e = ep;
state.u = client;
client.BeginReceive(new AsyncCallback(fuc), state); //首次触发接收数据方法
reciveButton.Enabled = false;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

private void fuc(IAsyncResult ar)
{
UdpClient u = (UdpClient)((UdpState)(ar.AsyncState)).u;
IPEndPoint e = (IPEndPoint)((UdpState)(ar.AsyncState)).e;

Byte[] reDatas = u.EndReceive(ar, ref e);

if (reDatas.Length > 0)
{
R = new byte[reDatas.Length];
R = reDatas;
if (recClient == null || recClient.IsAlive == false)
{
recClient = new Thread(showRec);
recClient.Start();//显示到界面
}
}
u.BeginReceive(new AsyncCallback(fuc), ar.AsyncState);
}
delegate void wakeShow();
private void showRec() //委托执行函数
{
if (!textMessage.InvokeRequired)
{
try
{
for (int i = 0; i < R.Length; i++)
{
textMessage.AppendText(R[i].ToString("X2"));
}

textMessage.AppendText("\n");
}
catch { }

textMessage.Refresh();
}
else
{
wakeShow show = new wakeShow(showRec);
Invoke(show);
}
}

这样写,首先局域网通信时成功的,但是,上面的服务器端,连着发了两条数据过来,但是客户端显示的接收值接收了后面那条数据。调试发现其实 Byte[] reDatas = u.EndReceive(ar, ref e);
这里接收是接收到了两次,但是,到下面用线程显示的时候 就只显示了一次
...全文
897 9 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
lizhibin11 2011-03-08
  • 打赏
  • 举报
回复

R = new byte[reDatas.Length];
R = reDatas;


这两句同样也有同步问题,既然你已经使用了异步socket,那么没有必要再使用thread,如果担心处理过程长而影响接收,可以把beginreceive放到处理之前,然后处理时只需要锁一次即可,不用新开thread再次加锁。
规范的做法是把接收到的数据copy到一个较大的缓冲区,然后有一个线程去处理那个大缓冲区中的各个包。
lizhibin11 2011-03-08
  • 打赏
  • 举报
回复
R和textMessage都属于全局变量,因为服务端是连着发送的,接收端会瞬间分出两个线程执行

for (int i = 0; i < R.Length; i++)
{
textMessage.AppendText(R[i].ToString("X2"));
}
textMessage.AppendText("\n");

此时R在两次接收中被赋予了不同的值,就会发生同步问题.所以在不同线程访问R和textMessage时,应该定义一个全局object obj = new object(),然后把上述代码放在

lock(obj)
{
//
}

中。
另外数据在发送和接收时,最好在包的开头定义数据长度(正式应用是必须的),这样可以准确判断是否接收到一个完整的包。
flyerwing 2011-03-08
  • 打赏
  • 举报
回复
51aspx上有哦以前上传的一个示例,也许对楼主有帮助.
zhangshuqiang123 2011-03-08
  • 打赏
  • 举报
回复
不是用了委托了吗?[Quote=引用 4 楼 awayy1432 的回复:]
后台线程不能直接访问控件的
可以加锁试试
或者忽略控件异常
[/Quote]
zhangshuqiang123 2011-03-08
  • 打赏
  • 举报
回复
能具体点吗?[Quote=引用 2 楼 lizhibin11 的回复:]
textMessage要加锁。
[/Quote]
脾气不坏 2011-03-08
  • 打赏
  • 举报
回复
后台线程不能直接访问控件的
可以加锁试试
或者忽略控件异常
flyerwing 2011-03-08
  • 打赏
  • 举报
回复
WHILE(TRUE)
{
//DOSOMETHING
}
这东西绝对得设计好的结构,要不很不好用.
还是花钱雇佣个大师吧
lizhibin11 2011-03-08
  • 打赏
  • 举报
回复
textMessage要加锁。
zhangshuqiang123 2011-03-08
  • 打赏
  • 举报
回复
CSDN的朋友们快来解救一下

111,098

社区成员

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

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

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