首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

C# C/S UDP一对多异步通信解决思路

2013-09-29 
C# C/S UDP一对多异步通信服务器端:public class StateObject{//服务器端public Socket udpServer null

C# C/S UDP一对多异步通信
服务器端:

public class StateObject
    {
        //服务器端
        public Socket udpServer = null;
        //接受数据缓冲区
        public byte[] buffer = new byte[10*1024];
        //远程终端
        public EndPoint remoteEP;

        public bool flag = false;
    }


  private void ServerForm_Load(object sender, EventArgs e)
        {
            StartServer startServer = new StartServer();
            thread = new Thread(new ThreadStart(startServer.ServerBind));
            thread.Start();
        }

 #region 服务器绑定终端节点
        public void ServerBind()
        {
            //主机IP
            IPEndPoint serverIp = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8686);
            Socket udpServer = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            udpServer.Bind(serverIp);
            IPEndPoint clientIp = new IPEndPoint(IPAddress.Any, 0);
            state = new StateObject();
            state.udpServer = udpServer;
            state.remoteEP = (EndPoint)clientIp;
            AsynRecive();
        }
        #endregion

        #region 异步接受消息
        public void AsynRecive()
        {
            lock (state)
            {
                state.udpServer.BeginReceiveFrom(state.buffer, 0, state.buffer.Length, SocketFlags.None, ref state.remoteEP,
                    new AsyncCallback(ReciveCallback), null);
                receiveDone.WaitOne();
            }
        }
        #endregion

        #region 异步接受消息回调函数
        public void ReciveCallback(IAsyncResult asyncResult)
        {
            if (asyncResult.IsCompleted)
            {
                //获取发送端的终节点
                IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 0);
                EndPoint remoteEP = (EndPoint)ipep;
                state.udpServer.EndReceiveFrom(asyncResult, ref remoteEP);
                data = new byte[10*1024];
                state.buffer.CopyTo(data, 0);
                state.buffer = new byte[10*1024];         
                int i = 0;
                ///取出命令
                for (i = 0; i < leng; i++)
                {
                    if (Convert.ToInt32(data[i]) == 0)    


                        break;
                }
                byte[] cmdbyte = new byte[i];
                for (int k = 0; k < i; k++)
                {
                    cmdbyte[k] = data[k];
                }
                commandStr = Encoding.ASCII.GetString(cmdbyte);
                if(!commandStr.Equals("connect"))
                MessageBox.Show(commandStr, "kkk");
                handleMsg(commandStr);

                state.remoteEP = remoteEP;
                receiveDone.Set();
                AsynRecive();//继续接受消息
            }
        }
        #endregion

        #region 异步发送消息
        public void AsynSend(byte[] buffer)
        {
            state.udpServer.BeginSendTo(buffer, 0, buffer.Length, SocketFlags.None, state.remoteEP,
                new AsyncCallback(SendCallback), null);
            sendDone.WaitOne();
        }
        #endregion

        #region 异步发送消息回调函数
        public void SendCallback(IAsyncResult asyncResult)
        {
            //消息发送完毕
            if (asyncResult.IsCompleted)
            {
                state.udpServer.EndSendTo(asyncResult);
            }
            sendDone.Set();
        }
        #endregion
 private void handleMsg(String msg)
{

}



客户端:
 public class StateObject
    {
        //客户端套接字
        public Socket udpClient = null;
        //接收信息缓冲区
        public byte[] buffer = new byte[10*1024];
        //服务器端终节点
        public IPEndPoint serverIp;
        //远程终端节点
        public EndPoint remoteEP;

    }

 private void 登陆_Load(object sender, EventArgs e)
        {
            contactWithServer = new ContactWithServer(this);
            clientcontactserverThread = new Thread(new ThreadStart(contactWithServer.AsynRecive));
            clientcontactserverThread.Start();           
        }


public ContactWithServer(登陆 loginForm)
        {
            this.loginForm = loginForm;
            state = new StateObject();
            state.udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            state.serverIp = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8686);


            state.remoteEP = (EndPoint)(new IPEndPoint(IPAddress.Any, 0));
            //此处注意:
            //  由于当前是客户端,所以没有绑定终节点
            //  不可直接接收消息,必须先向其他终端发送信息告知本机终节点
            string msg = "connect";
            byte[] buffer = Encoding.ASCII.GetBytes(msg);
            AsynSend(buffer);
        }
  #region 异步接收来自其他终端发送的消息
        public void AsynRecive()
        {
            state.udpClient.BeginReceiveFrom(state.buffer, 0, state.buffer.Length, SocketFlags.None, ref state.remoteEP,
                new AsyncCallback(ReciveCallback), null);
            receiveDone.WaitOne();
        }
        #endregion

        #region 异步接收来自其他终端发送的消息回调函数
        public void ReciveCallback(IAsyncResult asyncResult)
        {
            //信息接收完成
            if (asyncResult.IsCompleted)
            {
                state.udpClient.EndReceiveFrom(asyncResult, ref state.remoteEP);
                data=new byte[10*1024];
                state.buffer.CopyTo(data,0);
                if (data.Length < 20)                       //只有命令
                    commandStr = Encoding.ASCII.GetString(data);
                else                                       
                {
                    int i = 0;
                    ///取出命令
                    for (i = 0; i < leng; i++)
                    {
                        if (Convert.ToInt32(data[i]) == 0)    
                            break;
                    }
                    byte[] cmdbyte = new byte[i];
                    for (int k = 0; k < i; k++)
                    {
                        cmdbyte[k] = data[k];
                    }
                    commandStr = Encoding.ASCII.GetString(cmdbyte);
                }
                MessageBox.Show(commandStr, "来自服务器的命令!");
                handleMsg(commandStr);         
                state.buffer=new byte[10*1024];


                AsynRecive();
                receiveDone.Set();
            }
        }
        #endregion

 #region 异步发送消息
        public void AsynSend(byte[] buffer)
        {
            state.udpClient.BeginSendTo(buffer, 0, buffer.Length, SocketFlags.None, state.serverIp,
                new AsyncCallback(SendCallback), null);
            sendDone.WaitOne();
        }
        #endregion

        #region 异步发送消息回调函数
        public void SendCallback(IAsyncResult asyncResult)
        {
            //消息发送完成
            if (asyncResult.IsCompleted)
            {
                state.udpClient.EndSendTo(asyncResult);
            }
            sendDone.Set();
        }
        #endregion


上面的代码可以正确实现服务器与客户端一对一的通信,但是我现在需要一对多的,该怎样修改呢?
[解决办法]
   private delegate void WriteWrongLogHandle(string str);
        private delegate void WriteLogHandle(byte[] byteData);
        //本机IP地址
        private IPEndPoint localEP;
        //将要发送的IP地址
       // private EndPoint RemotePoint;
        //网络端口
        Socket listener = null;//udp
        private static bool isListener = true;//控制服务器监控服务

        Dictionary<string, EndPoint> dic = null; //IP信息字典
        private static readonly object padlock = new object();
        private int MessageLength;//数据包大小

        private int OperationCode;//操作内码
        private Socket handle;
        private BranchInfo info = null;
        private string BranchNo;//机构内码
        private int MsgThreadNum;//运行通讯线程数目
        private int PortNum;//端口数目
        private string ServerIp;//
        private ManualResetEvent receiveDone = null;
        private bool IsLog = false;     //是否写日志


        #region 服务启动
        protected override void OnStart(string[] args)
        {
            try
            {
                // TODO: 在此处添加代码以启动服务。

                //启动PosConm服务时开始写日志
               // Utils.WriteLogFile("正在启动ConsumeSmg服务...");
                String strFileName = AppDomain.CurrentDomain.BaseDirectory + "\\ConsumeMsg.xml";
                XmlDocument doc = new XmlDocument();
                doc.Load(strFileName);


                //   WriteExceptionLog(strFileName);
                XmlNodeList listNode = doc.GetElementsByTagName("settings");
                foreach (XmlNode node in listNode[0].ChildNodes)
                {
                    switch (node.Name)
                    {
                        case "ServerIp":
                            ServerIp = node.InnerText;
                            break;
                        case "PortNum":
                            PortNum = Convert.ToInt32(node.InnerText);
                            break;
                        case "MsgThreadNum":
                            MsgThreadNum = Convert.ToInt32(node.InnerText);
                            break;
                        case "IsLog":
                            IsLog = Convert.ToBoolean(Convert.ToInt32(node.InnerText));
                            break;
                        default:
                            break;
                    }
                }
                if (IsLog)
                {
                    WriteExceptionLog("正在启动ConsumeSmg服务...");
                }
                dic = new Dictionary<string, EndPoint>(); //IP信息字典
                info = new BranchInfo();
                receiveDone = new ManualResetEvent(false); 
                listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);//udp
                localEP = new IPEndPoint(IPAddress.Any, PortNum);
                listener.Bind(localEP);
                isListener = true;
                if (IsLog)
                {
                    WriteExceptionLog(ServerIp + "[" + PortNum + "]");
                }

                try
                {


                    //开多线程通讯
                    //for (int i = 0; i < MsgThreadNum; i++)
                    //{
                    Thread acceptWorkThread = new Thread(AcceptWorkThread);
                    acceptWorkThread.Start();
                    //}

                    Thread updateDicThread = new Thread(new ThreadStart(UpdateDictionaryThread));
                    updateDicThread.Start();


                }
                catch (Exception ex)
                {
                    if (IsLog)
                    {
                        WriteExceptionLog("开始启动接收线程" + ex.Message);
                    }

                }
            }
            catch (Exception ex)
            {
                if (IsLog)
                {
                    WriteExceptionLog("启动服务失败:" + ex.Message);
                }
                Stop();
            }
        }
        #endregion

        public void AcceptWorkThread()
        {
            ////本机IP从XML文件中读取

            try
            {
               
           
                //异步接收数据

                info = new BranchInfo();
                info.Socket = listener;
                listener.BeginReceiveFrom(info.Buffer, 0, info.Buffer.Length, SocketFlags.None, ref info.RePoint, new AsyncCallback(ReceiveCallBack), info);
                receiveDone.WaitOne();
                Thread.Sleep(100);
                if (IsLog)
                {
                    WriteExceptionLog("打印从客户端传输过来的字节数组");
                }
                
                //WriteByteDataLog(info.Buffer);
                
            }
            catch (Exception ex)
            {
                if (IsLog)


                {
                    WriteExceptionLog("异步接收短消息" + ex.Message);
                }
                Stop();  
            }
        }
服务端
[解决办法]
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace tti365.ConsumeSmg365WS.Common
{
    class BranchInfo
    {
        private byte[] _Buffer = new byte[4 * 1024];//接收数据缓存
        private Socket _Socket;//客户端套接字
        private int _MessageLength;//文件头大小

        private int _OperationCode;//操作码

        private byte[] _SendBuffer = new byte[4 * 1024];//发送数据的缓存
        private int _ErrorTime;
        private string _BranchNo;
        private DateTime _Time;
        public EndPoint RePoint =(EndPoint)new IPEndPoint(IPAddress.Any,0) ;
       
        /// <summary>
        /// UDP 套接字包
        /// </summary>
        public Socket Socket
        {
            set { _Socket = value; }
            get { return _Socket; }
        }

        /// <summary>
        /// 发送短IP
        /// </summary>
        //public EndPoint RePoint
        //{
        //    set { _RePoint = value; }
        //    get { return _RePoint; }
        //}

        /// <summary>
        /// 数据缓存包

        /// </summary>
        public byte[] Buffer
        {
            set { _Buffer = value; }
            get { return _Buffer; }
        }

        /// <summary>
        /// 数据包大小

        /// </summary>
        public int MessageLength
        {
            set { _MessageLength = value; }
            get { return _MessageLength; }
        }

        /// <summary>
        /// 操作码

        /// </summary>
        public int OperationCode
        {
            set { _OperationCode = value; }
            get { return _OperationCode; }
        }

        /// <summary>
        /// 发送数据包
        /// </summary>
        public byte[] SendBuffer
        {
            set { _SendBuffer = value; }
            get { return _SendBuffer; }


        }

        /// <summary>
        /// 错误次数
        /// </summary>
        public int ErrorTime
        {
            set { _ErrorTime = value; }
            get { return _ErrorTime; }
        }

        /// <summary>
        /// 接收机构类码
        /// </summary>
        public string BranchNo
        {
            set { _BranchNo = value; }
            get { return _BranchNo; }
        }


        /// <summary>
        /// 时间
        /// </summary>
        public DateTime Time
        {
            set { _Time = value; }
            get { return _Time; }
        }
    }
}

[解决办法]
C# C/S UDP一对多异步通信解决思路

热点排行