我大概看了一下UDPClient和TCPClient的类,有些想不明白,望大家指教:
send方法好说,不过receive方法有些迷惑,它是同步的,也就是说我启动receive方法后,直到等到有数据了,才能接收到,才能再做别的事情。那我能想到的一般的解决方案是开一个线程,反复轮询接收数据,另一个线程是用来发送数据的。一般的聊天软件是这么设计的吗?
谢谢指教。

解决方案 »

  1.   

    BeginReceive是异步的,我知道,但代码怎么设计呢?msdn上的模式都是BeginReceive后,可以干别的事情。
    这里我能想象的代码模式是,无限循环这个BeginReceive方法,作为接收数据用(类似于监听),至于Send方法,无所谓在什么时候,与接收是无关的。不知道我的理解对吗?
      

  2.   

    原文:http://www.cnblogs.com/idior/articles/147648.html
      

  3.   

    服务器端        //开启服务
            private void BeginService_Click(object sender, EventArgs e) {
                try {
                    this.btnBegin.Enabled = false;
                    Socket listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    listen.Bind(server_ip);
                    listen.Listen(LISTEN_NUM);
                    listen.BeginAccept(new AsyncCallback(OnConnectRequest), listen);
                } catch (Exception) {
                    return;
                }
            }        //开始侦听
            public void OnConnectRequest(IAsyncResult ar) {
                Socket listener = ar.AsyncState as Socket;
                client = listener.EndAccept(ar);            client.BeginReceive(msgBuff, 0, msgBuff.Length, SocketFlags.None, new AsyncCallback(OnRecievedData), client);
                listener.BeginAccept(new AsyncCallback(OnConnectRequest), listener);
            }        //接收数据
            public void OnRecievedData(IAsyncResult ar) {
                Socket listener = ar.AsyncState as Socket;
                try {
                    int nBytesRec = listener.EndReceive(ar);                if (nBytesRec > 0) {
                        //byte ==> string
                        string sRecieved = Encoding.Unicode.GetString(msgBuff, 0, nBytesRec);                    //处理来自客户端的消息 
                        ProcessMessage(listener, sRecieved);                    //注册消息回调函数
                        SetupRecieveCallback(listener);                    //listener.Send(Encoding.Unicode.GetBytes(string.Format("Begin|kkun|kkun|{0}", user_list.Count <= 1)));
                    } else {
                        this.Invoke(new Action<IPEndPoint>(Tstring_User_Remove), listener.RemoteEndPoint);
                        this.Invoke(new Action<string>(Tstring_Info), string.Format("disconnect from server {0}", listener.RemoteEndPoint));
                        listener.Shutdown(SocketShutdown.Both);
                        listener.Close();
                        //continue;
                    }
                } catch(Exception exp) {
                    this.Invoke(new Action<IPEndPoint>(Tstring_User_Remove), listener.RemoteEndPoint);
                    this.Invoke(new Action<string>(Tstring_Info), string.Format("disconnect from server {0}", listener.RemoteEndPoint));
                    this.Invoke(new Action<string>(Tstring_Info), string.Format("disconnect from server {0}", exp.Message));
                    listener.Shutdown(SocketShutdown.Both);
                    listener.Close();
                }
            }        //处理接收到的消息
            private void ProcessMessage(Socket listener, string sRecieved) {
                //如果接收到的消息不为空的话
                if (!string.IsNullOrEmpty(sRecieved)) {
                    //新客户端
                    UserInfo info = new UserInfo();                //定义消息格式
                    /*
                     * Command|UserName|UserPass|UserType
                     * Command|UserName|pbSource|pbTarget
                     */
                    #region 处理命令
                    string[] str = sRecieved.Split('|');
                    string _Command = string.Empty;
                    if (str.Length >= 4) {
                        byte[] bSend = Encoding.Unicode.GetBytes(sRecieved);
                        switch (str[0]) {
                            case "Login":
                                #region 登录
                                //用户名
                                if (!string.IsNullOrEmpty(str[1])) {
                                    info.UserName = str[1];
                                }
                                //密码
                                if (!string.IsNullOrEmpty(str[2])) {
                                    info.UserPass = str[2];
                                }
                                //玩家类型,如红方,黑方
                                if (!string.IsNullOrEmpty(str[3])) {
                                    info.UserType = str[3];
                                }
                                //保存客户端连接
                                if (null == info.UserSocket) {
                                    info.UserSocket = listener;
                                }                            //添加到用户列表中
                                if (!user_list.ContainsKey(info.UserName)) {
                                    user_list.Add(info.UserName, info);
                                    this.Invoke(new Action<IPEndPoint>(Tstring_User), listener.RemoteEndPoint);
                                }                            bSend = Encoding.Unicode.GetBytes(string.Format("Begin|kkun|kkun|{0}", user_list.Count));
                                //foreach (UserInfo item in user_list.Values) {
                                //    if (item != null && item.UserName != str[1]) {
                                //        item.UserSocket.Send(bSend);
                                //    }
                                //}
                                client.Send(bSend);                            break;
                                #endregion
                            case "Step":
                            case "Eat":
                            case "Back":
                            case "ToFaild":
                                foreach (UserInfo item in user_list.Values) {
                                    if (item != null && item.UserName != str[1]) {
                                        item.UserSocket.Send(bSend);
                                    }
                                }
                                break;
                            case "Begin":
                                bSend = Encoding.Unicode.GetBytes(string.Format("Begin|{0}|{0}|{1}", str[1], user_list.Count));
                                foreach (UserInfo item in user_list.Values) {
                                    if (item != null && item.UserName != str[1]) {
                                        item.UserSocket.Send(bSend);
                                    }
                                }
                                break;
                            default:
                                break;
                        }
                        this.Invoke(new Action<string>(Tstring_Info), string.Format(" > {0}", sRecieved));
                    } else {
                        //未定义的命令
                        this.Invoke(new Action<string>(Tstring_Info), string.Format("Undefined Command:{0}", sRecieved));                    byte[] bSend = Encoding.Unicode.GetBytes(sRecieved);
                        foreach (UserInfo item in user_list.Values) {
                            if (item != null && item.UserName != str[1]) {
                                item.UserSocket.Send(bSend);
                            }
                        }
                    }
                    #endregion            }
            }        //注册消息接收回调
            public void SetupRecieveCallback(Socket listener) {
                try {
                    AsyncCallback recieveData = new AsyncCallback(OnRecievedData);
                    listener.BeginReceive(msgBuff, 0, msgBuff.Length, SocketFlags.None, recieveData, listener);
                } catch (Exception ex) {
                    this.Invoke(new Action<string>(Tstring_Info),ex.Message);
                }
            }
      

  4.   

            /// <summary>
            /// 登录
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void MenuItem_Click_Login(object sender, RoutedEventArgs e) {
                try {
                    client = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
                    client.Blocking = false;
                    client.BeginConnect(clientInfo.ServerIPEndPoint, new AsyncCallback(OnConnect), client);
                } catch (Exception exp) {
                    throw exp;
                }
            }        #region 网络连接类
            //连接上服务器后,准备接收消息
            public void OnConnect(IAsyncResult ar) {
                System.Net.Sockets.Socket sock = (System.Net.Sockets.Socket)ar.AsyncState;
                try {
                    if (sock.Connected) {
                        //连接上服务器后,发送登录消息
                        string _Command = string.Format("Login|{0}|{1}|{2}", clientInfo.UserName, clientInfo.UserName, clientInfo.UserName);
                        byte[] _bCommand = Encoding.Unicode.GetBytes(_Command);
                        client.Send(_bCommand);                    AsyncCallback recieveData = new AsyncCallback(OnRecievedData);
                        sock.BeginReceive(msgBuff, 0, msgBuff.Length, System.Net.Sockets.SocketFlags.None, recieveData, sock);
                    }
                } catch (Exception ex) {
                    throw ex;
                }
            }        //接收消息
            public void OnRecievedData(IAsyncResult ar) {
                System.Net.Sockets.Socket sock = (System.Net.Sockets.Socket)ar.AsyncState;
                try {
                    int nBytesRec = sock.EndReceive(ar);
                    if (nBytesRec > 0) {
                        string sRecieved = Encoding.Unicode.GetString(msgBuff, 0, nBytesRec);
                        ProcessMessage(sock, sRecieved);
                        SetupRecieveCallback(sock);
                    } else {
                        sock.Shutdown(System.Net.Sockets.SocketShutdown.Both);
                        sock.Close();
                    }
                } catch (Exception exp) {
                    sock.Shutdown(System.Net.Sockets.SocketShutdown.Both);
                    sock.Close();
                    throw exp;
                }
            }        //注册消息接收回调函数
            public void SetupRecieveCallback(System.Net.Sockets.Socket sock) {
                try {
                    AsyncCallback recieveData = new AsyncCallback(OnRecievedData);
                    sock.BeginReceive(msgBuff, 0, msgBuff.Length, System.Net.Sockets.SocketFlags.None, recieveData, sock);
                } catch (Exception ex) {
                    MessageBox.Show(ex.Message);
                    this.Close();
                }
            }        //处理接收到的消息
            private void ProcessMessage(System.Net.Sockets.Socket listener, string sRecieved) {
                //如果接收到的消息不为空的话
                if (!string.IsNullOrEmpty(sRecieved)) {
                    #region 处理命令
                    string[] str = sRecieved.Split('|');
                    string _Command = string.Empty;
                    ChessDetail pbSource, pbTarget;
                    if (str.Length >= 4) {
                        switch (str[0].ToLower()) {
                            case "login":
                                this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new InitializeControlsDelegate(this.InitializeControls), int.Parse(str[3]));
                                break;
                            case "step":
                                pbSource = list[-int.Parse(str[2])];
                                pbTarget = list[-int.Parse(str[3])];
                                this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Tstring_Step_Delegate(this.Tstring_Step_Server), pbSource, pbTarget);
                                break;
                            case "eat":
                                pbSource = list[-int.Parse(str[2])];
                                pbTarget = list[-int.Parse(str[3])];
                                this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Tstring_Eat_Delegate(this.Tstring_Eat_Server), pbSource, pbTarget);
                                break;
                            case "back":
                            case "tofaild":
                            case "begin":
                                this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new InitializeControlsDelegate(this.InitializeControls), int.Parse(str[3]));
                                break;
                            default:
                                break;
                        }
                    }
                    #endregion
                }
            }
            #endregion
      

  5.   

    blog.csdn.net/lanwilliam
    里面网络编程中有我搜集的Socket开发的很多实例,也有我封装的简化的Socket的两个类
    那两个类是用在pda于pc无线通信的,所以只取最简化方法。