UDP如何循环接收消息。。。

时间:2022-12-15 16:00:46
如何能做到,一来消息就能接收到,
遇到的问题是,只能到第一条消息,从第二条开始都收不到了,按MSDN上说的,应该是EndRecive方法调用后就返回了,不可再使用,如何使它能循环接收消息?我的意思是说,像QQ那样,有消息就接收
另外,已经试过在BeginRecive和EndRecive方法外加while(true)了,都报错,

附全部代码如下,

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace Chat {
    public partial class ChatRoom : Form {

        private int port = 8000;
        private UdpClient client;
        private IPEndPoint ip;
        public ChatRoom() {
            InitializeComponent();
            InitUdp();
        }

        #region
        private void ChatRoom_FormClosing(object sender, FormClosingEventArgs e) {
            this.Dispose(true);
        }

        #region Send Message
        private void SendMessage(string str,IPEndPoint ip) {
            client = new UdpClient();
            client.Connect(ip);
            byte[] sMsg = Encoding.ASCII.GetBytes(str);
            try {
                client.Send(sMsg, sMsg.Length);
            }
            catch (Exception exp) {
                throw exp;
            }
            finally {
                this.tbMessage.Text = "";
            }
        }
        #endregion

        #region Recive
        private void InitUdp() {
            ip = new IPEndPoint(IPAddress.Any, port);
            client = new UdpClient(ip);

            RequestState rs = new RequestState();
            rs.ip = ip;
            rs.client = client;
            client.BeginReceive(new AsyncCallback(ReqCallback), rs);
        }

        private void ReqCallback(IAsyncResult ar) {
            RequestState rs = (RequestState)ar.AsyncState;
            UdpClient client = rs.client;
            IPEndPoint ip = rs.ip;
            rs.buffer = client.EndReceive(ar, ref ip);
            this.Invoke(new MessageDelegate(Message), rs);
        }

        private delegate void MessageDelegate(RequestState rs);
        private void Message(RequestState rs) {
            this.tbContent.Text += "From Server:"+Encoding.ASCII.GetString(rs.buffer)+"\n";
        }
        #endregion

        private void btnSend_Click(object sender, EventArgs e) {
            ip = new IPEndPoint(IPAddress.Parse(tbIp.Text), 8000);
            if (!string.IsNullOrEmpty(tbMessage.Text.Trim()))
                if (!string.IsNullOrEmpty(tbIp.Text.Trim()))
                    SendMessage(tbMessage.Text, ip);
        }

        #endregion

        private void btnEsc_Click(object sender, EventArgs e) {
            this.Dispose(true);
        }

    }


    public class RequestState {
        public RequestState() { }
        public  UdpClient client;
        public IPEndPoint ip;
        public byte[] buffer;
    }
}

15 个解决方案

#1



public  void Listener() 
{

while(true) 
{
IPEndPoint endpoint = null;
Byte[] data = this._mClient.Receive(ref endpoint);

}
}

#2


还是只能接收一次,试过了,
代码如下
            Thread thread = new Thread(new ThreadStart(InitUdp));
            thread.Start();

        private void InitUdp() {
            ip = new IPEndPoint(IPAddress.Any, port);
            client = new UdpClient(ip);

            RequestState rs = new RequestState();
            rs.ip = ip;
            rs.client = client;
            while (true) {
                rs.buffer = this.client.Receive(ref rs.ip);
                if(rs.ip!=null)
                    this.Invoke(new MessageDelegate(Message), rs);
            }
            //client.BeginReceive(new AsyncCallback(ReqCallback), rs);
        }

#3


没看懂?
例如 
 
private void Form1_Load(object sender, System.EventArgs e)
{
  #region ----InitSocket----
  try
  {
string hostname=Dns.GetHostName();
IPHostEntry hostip=Dns.Resolve(hostname);
IPAddress[] addrList=hostip.AddressList;
if(addrList.Length >0)
{
try
{
  this._mClient = new UdpClient(_AcptSocket);//初始化udp
        }
catch(Exception ex)
{ MessageBox.Show("接收端口被占用,请修改配置文件调整端口!");
}
         }
  }
  catch
  {

  }
  this._Listen = new Thread(new ThreadStart(this.Listener));
  this._Listen.IsBackground = true;
  this._Listen.Start();
}

public  void Listener() 
{
  Thread.Sleep(30);
  while(true) 
  {
IPEndPoint endpoint = null;
Byte[] data = this._mClient.Receive(ref endpoint);
}
  }
}



#4


推荐楼主看看牧野的这篇关于异步编程的文章:http://blog.csdn.net/wzd24/archive/2007/10/12/1821340.aspx

#5


楼主的问题应该是在ReqCallback方法中没有向系统投递下一个接收请求

#6


顶,楼上正解了.楼主用费步接收,但没有向系统投递下一个接收请求

#7


to jiatong1981:
很感谢,你那段代码看着是没问题,在你的代码的基础上,加上界面之类的操作,差不多就是一楼贴的代码,
第一次运行没问题,发送,接收都正常,第二次往后,就都接受不到了,能帮我看看吗,贴得是全部代码了

to wuhq030710914:
一开始就是用的SOCKET,参见( http://topic.csdn.net/u/20071204/17/a623d012-ead0-4480-a185-32f7cd2e420c.html)也是有问题无法解决才改成UDP的,现在只想解决UDP的问题,谢谢关注

#8


要么循环同步接收,要么连续异步

        private void ReqCallback(IAsyncResult ar) {
            RequestState rs = (RequestState)ar.AsyncState;
            UdpClient client = rs.client;
            IPEndPoint ip = rs.ip;
            rs.buffer = client.EndReceive(ar, ref ip);
            this.Invoke(new MessageDelegate(Message), rs);
            //下面想办法接着异步就可以了
             //比如:
           /*
            ip = new IPEndPoint(IPAddress.Any, port);
            RequestState rs = new RequestState();
            rs.ip = ip;
            rs.client = client;
            client.BeginReceive(new AsyncCallback(ReqCallback), rs);
           */
        }


楼主的这种实现不太直观,事实上AsyncResult完全可以包括你需要的数据和变量,没必要构造RequestState,这样MessageDelegate委托可以遵循一般的(object sender,EventArgs的派生类 e)的签名

#9


private UdpClient m_Client;

        private Thread t;
        //private Thread tfileWathcer;
        private int LocalPort = 6868;
        private IPAddress m_GroupAddress;

        private bool m_Done = false;

#region UDP监听初始化
        public void Initialize()
        {
            //
            // instantiate UdpCLient
            //
            m_Client = new UdpClient(LocalPort);

            //
            // Create an object for Multicast Group
            //

            m_GroupAddress = IPAddress.Parse("224.0.0.1");

            //
            // Join Group
            //
            try
            {
                m_Client.JoinMulticastGroup(m_GroupAddress, 100);
            }
            catch (Exception)
            {
                this.richTextBox1.Text += "Unable to join multicast group\n";
            }
        }
        #endregion

        #region 监听UDP消息
        public void Listener()
        {

            //
            // The listener waits for data to come
            // and buffers it

            Thread.Sleep(2000); // make sure client2 is receiving

            Encoding ENCODING = Encoding.Default;

            while (!m_Done)
            {
                IPEndPoint endpoint = null;
                Byte[] data = m_Client.Receive(ref endpoint);

                String strData = ENCODING.GetString(data);

                string[] deviceAndcmd = strData.Split("|".ToCharArray());

                if (deviceAndcmd[0] != "CMD")
                    continue;

                this.richTextBox1.Text = "收到消息\n" + strData;
                this.richTextBox2.Text = "----------消息----------\n" +
                                        strData +
                                        "\n----------处理消息----------\n" + 
                                        ExeCommand(deviceAndcmd[1]);
            }
        }
        #endregion

#10


if (button2.Text == "开始监听")
            {
                button2.Text = "停止监听";

                Initialize();

                t = new Thread(new ThreadStart(Listener));
                t.Start();

                return;
            }

            if (button2.Text == "停止监听")
            {
                button2.Text = "开始监听";

                m_Client.DropMulticastGroup(m_GroupAddress);
                m_Client.Close();

                t.Abort();
            }

#11


楼主的问题应该是在ReqCallback方法中没有向系统投递下一个接收请求
-----------------------------------------------------------
行不行,楼主给个答复呀

#12


//楼主的问题应该是在ReqCallback方法中没有向系统投递下一个接收请求 
在UDP中,不知道如何向系统投递下一个接收请求,我试着写
        private void InitUdp() {
            ip = new IPEndPoint(IPAddress.Any, port);
            client = new UdpClient(ip);

            RequestState rs = new RequestState();
            rs.ip = ip;
            rs.client = client;
            client.BeginReceive(new AsyncCallback(ReqCallback), rs);
        }

        private void ReqCallback(IAsyncResult ar) {
            RequestState rs = (RequestState)ar.AsyncState;
            UdpClient client = rs.client;
            IPEndPoint ip = rs.ip;
            rs.buffer = client.EndReceive(ar, ref ip);
            this.Invoke(new MessageDelegate(Message), rs);
            client.BeginReceive(new AsyncCallback(ReqCallback), rs);//这里实现向系统投递下一个请求,但是不行
        }


结果连第一次的也接收不到了

#13


            Thread thread = new Thread(new ThreadStart(Listen));
            thread.Start();

        private void Listen() {
            string message = string.Empty;
            while (true) {
                IPEndPoint endpoint = null;
                Byte[] data = this.client.Receive(ref endpoint);
                if (data != null) {
                    message = Encoding.ASCII.GetString(data);
                    this.Invoke(new MessageDelegateString(Message), message);
                }
                Thread.Sleep(100);
            }
        }

这样写,也是只能接收到第一次的消息,往后的都不再显示

#14


上边的代码,第一次执行,走到
Byte[] data = this.client.Receive(ref endpoint);

主线程继续执行,等待异步返回


我发送消息后,断点回到这里,data有数据,显示到界面上,
继续执行到死循环,第二次到达这里再次触发断点,
Byte[] data = this.client.Receive(ref endpoint);

主线程继续执行,等待异步返回

再次发送消息,没有触发断点。。。。。
client = new UdpClient();
            client.Connect(ip);
            byte[] sMsg = Encoding.ASCII.GetBytes(str);
            try {
                client.Send(sMsg, sMsg.Length);
            }
            catch (Exception exp) {
                throw exp;
            }
            finally {
                this.tbMessage.Text = "";
            }

没有触发断点!应该是哪的问题!

#15


#1



public  void Listener() 
{

while(true) 
{
IPEndPoint endpoint = null;
Byte[] data = this._mClient.Receive(ref endpoint);

}
}

#2


还是只能接收一次,试过了,
代码如下
            Thread thread = new Thread(new ThreadStart(InitUdp));
            thread.Start();

        private void InitUdp() {
            ip = new IPEndPoint(IPAddress.Any, port);
            client = new UdpClient(ip);

            RequestState rs = new RequestState();
            rs.ip = ip;
            rs.client = client;
            while (true) {
                rs.buffer = this.client.Receive(ref rs.ip);
                if(rs.ip!=null)
                    this.Invoke(new MessageDelegate(Message), rs);
            }
            //client.BeginReceive(new AsyncCallback(ReqCallback), rs);
        }

#3


没看懂?
例如 
 
private void Form1_Load(object sender, System.EventArgs e)
{
  #region ----InitSocket----
  try
  {
string hostname=Dns.GetHostName();
IPHostEntry hostip=Dns.Resolve(hostname);
IPAddress[] addrList=hostip.AddressList;
if(addrList.Length >0)
{
try
{
  this._mClient = new UdpClient(_AcptSocket);//初始化udp
        }
catch(Exception ex)
{ MessageBox.Show("接收端口被占用,请修改配置文件调整端口!");
}
         }
  }
  catch
  {

  }
  this._Listen = new Thread(new ThreadStart(this.Listener));
  this._Listen.IsBackground = true;
  this._Listen.Start();
}

public  void Listener() 
{
  Thread.Sleep(30);
  while(true) 
  {
IPEndPoint endpoint = null;
Byte[] data = this._mClient.Receive(ref endpoint);
}
  }
}



#4


推荐楼主看看牧野的这篇关于异步编程的文章:http://blog.csdn.net/wzd24/archive/2007/10/12/1821340.aspx

#5


楼主的问题应该是在ReqCallback方法中没有向系统投递下一个接收请求

#6


顶,楼上正解了.楼主用费步接收,但没有向系统投递下一个接收请求

#7


to jiatong1981:
很感谢,你那段代码看着是没问题,在你的代码的基础上,加上界面之类的操作,差不多就是一楼贴的代码,
第一次运行没问题,发送,接收都正常,第二次往后,就都接受不到了,能帮我看看吗,贴得是全部代码了

to wuhq030710914:
一开始就是用的SOCKET,参见( http://topic.csdn.net/u/20071204/17/a623d012-ead0-4480-a185-32f7cd2e420c.html)也是有问题无法解决才改成UDP的,现在只想解决UDP的问题,谢谢关注

#8


要么循环同步接收,要么连续异步

        private void ReqCallback(IAsyncResult ar) {
            RequestState rs = (RequestState)ar.AsyncState;
            UdpClient client = rs.client;
            IPEndPoint ip = rs.ip;
            rs.buffer = client.EndReceive(ar, ref ip);
            this.Invoke(new MessageDelegate(Message), rs);
            //下面想办法接着异步就可以了
             //比如:
           /*
            ip = new IPEndPoint(IPAddress.Any, port);
            RequestState rs = new RequestState();
            rs.ip = ip;
            rs.client = client;
            client.BeginReceive(new AsyncCallback(ReqCallback), rs);
           */
        }


楼主的这种实现不太直观,事实上AsyncResult完全可以包括你需要的数据和变量,没必要构造RequestState,这样MessageDelegate委托可以遵循一般的(object sender,EventArgs的派生类 e)的签名

#9


private UdpClient m_Client;

        private Thread t;
        //private Thread tfileWathcer;
        private int LocalPort = 6868;
        private IPAddress m_GroupAddress;

        private bool m_Done = false;

#region UDP监听初始化
        public void Initialize()
        {
            //
            // instantiate UdpCLient
            //
            m_Client = new UdpClient(LocalPort);

            //
            // Create an object for Multicast Group
            //

            m_GroupAddress = IPAddress.Parse("224.0.0.1");

            //
            // Join Group
            //
            try
            {
                m_Client.JoinMulticastGroup(m_GroupAddress, 100);
            }
            catch (Exception)
            {
                this.richTextBox1.Text += "Unable to join multicast group\n";
            }
        }
        #endregion

        #region 监听UDP消息
        public void Listener()
        {

            //
            // The listener waits for data to come
            // and buffers it

            Thread.Sleep(2000); // make sure client2 is receiving

            Encoding ENCODING = Encoding.Default;

            while (!m_Done)
            {
                IPEndPoint endpoint = null;
                Byte[] data = m_Client.Receive(ref endpoint);

                String strData = ENCODING.GetString(data);

                string[] deviceAndcmd = strData.Split("|".ToCharArray());

                if (deviceAndcmd[0] != "CMD")
                    continue;

                this.richTextBox1.Text = "收到消息\n" + strData;
                this.richTextBox2.Text = "----------消息----------\n" +
                                        strData +
                                        "\n----------处理消息----------\n" + 
                                        ExeCommand(deviceAndcmd[1]);
            }
        }
        #endregion

#10


if (button2.Text == "开始监听")
            {
                button2.Text = "停止监听";

                Initialize();

                t = new Thread(new ThreadStart(Listener));
                t.Start();

                return;
            }

            if (button2.Text == "停止监听")
            {
                button2.Text = "开始监听";

                m_Client.DropMulticastGroup(m_GroupAddress);
                m_Client.Close();

                t.Abort();
            }

#11


楼主的问题应该是在ReqCallback方法中没有向系统投递下一个接收请求
-----------------------------------------------------------
行不行,楼主给个答复呀

#12


//楼主的问题应该是在ReqCallback方法中没有向系统投递下一个接收请求 
在UDP中,不知道如何向系统投递下一个接收请求,我试着写
        private void InitUdp() {
            ip = new IPEndPoint(IPAddress.Any, port);
            client = new UdpClient(ip);

            RequestState rs = new RequestState();
            rs.ip = ip;
            rs.client = client;
            client.BeginReceive(new AsyncCallback(ReqCallback), rs);
        }

        private void ReqCallback(IAsyncResult ar) {
            RequestState rs = (RequestState)ar.AsyncState;
            UdpClient client = rs.client;
            IPEndPoint ip = rs.ip;
            rs.buffer = client.EndReceive(ar, ref ip);
            this.Invoke(new MessageDelegate(Message), rs);
            client.BeginReceive(new AsyncCallback(ReqCallback), rs);//这里实现向系统投递下一个请求,但是不行
        }


结果连第一次的也接收不到了

#13


            Thread thread = new Thread(new ThreadStart(Listen));
            thread.Start();

        private void Listen() {
            string message = string.Empty;
            while (true) {
                IPEndPoint endpoint = null;
                Byte[] data = this.client.Receive(ref endpoint);
                if (data != null) {
                    message = Encoding.ASCII.GetString(data);
                    this.Invoke(new MessageDelegateString(Message), message);
                }
                Thread.Sleep(100);
            }
        }

这样写,也是只能接收到第一次的消息,往后的都不再显示

#14


上边的代码,第一次执行,走到
Byte[] data = this.client.Receive(ref endpoint);

主线程继续执行,等待异步返回


我发送消息后,断点回到这里,data有数据,显示到界面上,
继续执行到死循环,第二次到达这里再次触发断点,
Byte[] data = this.client.Receive(ref endpoint);

主线程继续执行,等待异步返回

再次发送消息,没有触发断点。。。。。
client = new UdpClient();
            client.Connect(ip);
            byte[] sMsg = Encoding.ASCII.GetBytes(str);
            try {
                client.Send(sMsg, sMsg.Length);
            }
            catch (Exception exp) {
                throw exp;
            }
            finally {
                this.tbMessage.Text = "";
            }

没有触发断点!应该是哪的问题!

#15