希望实现的功能:1.实时的现实所有的客户端是否在线,即一开启程序,就检测所有的客户端,把在线的彩色现实,并都排在前面;不在线的都灰色现实,都排在后面。要求一定要用异步的实现。
现在我用异步的方式出现的问题是:1.当客户端程序第一次运行时,服务器端程序才会检测到客户端是否在线,并把他彩色或灰色显示。但关掉客户端程序再次启动时,服务器端程序就不去检测客户端是否在线了。(这个问题让我很郁闷)     2.(这个问题有时会出现)当关掉客户端程序再次启动时,会弹出“什么端口只能使用一次”的异常(记不太清了,明天会补详细点)。不知道我出现的问题有没有人碰到过?
明天我会把代码贴出来的。

解决方案 »

  1.   

    1.你在服务端接收连接请求时,更新在线状态即可,如果不行,只能是你代码实现的问题.
    2.这个涉及到端口重用的问题,你可以使用端口重用参数设置Socket,或者断开时设定立即断开连接.
      

  2.   


    1、客户端掉线时(或关闭时),服务端没有及时得知其已下线,并及时刷新其状态显示;解决办法:通过设置Socket低级参数,使得服务端及时得知掉线;
    通过客户端关闭时发送下线消息给服务端进行通知;2、可能程序上不小心设置了接受同一个客户端连接时,使用了同一个端口,这将导致同一个客户端快速断线重连时,服务端出现那个错误解决办法:
    对每一个客户端连接,都使用随机端口,而非固定端口
      

  3.   

    补充:
    写完了发现问题2有点问题按理说Scoket服务端在同一个端口上侦听连接,收到了就创建Socket实例,服务端的端口是始终不变的。不应该出现这个情况。疑惑是不是你的“服务”实际上是Socket客户端而你的“客户”实际上是Sokcet服务端?Socekt服务端负责Listen
    SOcket客户端负责Connect
      

  4.   

    如果你的描述果然是反的,那么问题2其实和问题1有些关联。Socket客户端关闭时未能把Socket链接Shutdown掉,导致再次尝试连接时,出现端口被占用的错误。
      

  5.   

    贴出我的代码,高人们给看一下。服务器代码:
    namespace WpfServer1
    {
        public partial class Window1 : Window
        {
            private int listenport = 5555;
            private StateObject state;
            private Socket _svrSock;
            private static ManualResetEvent Done = new ManualResetEvent(false); //用来把在线不在线分开显示的
            public ArrayList list = new ArrayList();//存储在线的用户socket
            public ObservableCollection<Machines> _machineItem = new ObservableCollection<Machines>();
            string FilePath = AppDomain.CurrentDomain.BaseDirectory.ToString() + @"\Machine.xml";
            private delegate void SetListView();        private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                if (File.Exists(FilePath))
                {
                    _machineItem = GetLocalMachineItems();
                    lstClients.ItemsSource = _machineItem;
                }            Thread th = new Thread(new ThreadStart(StartListening));
                th.Start();
            }        // 获得所有的播放机,并让其初始化时图片为灰色
            public ObservableCollection<Machines> GetLocalMachineItems()
            {
                ObservableCollection<Machines> lst = new ObservableCollection<Machines>();
                XmlDocument doc = new XmlDocument();
                doc.Load("Machine.xml");
                foreach (XmlNode node in doc.SelectSingleNode("groups").ChildNodes)
                {
                    lst.Add(new Machines("Images/ComputerGray.png", node));
                }
                return lst;
            } //开始连接
            public void StartListening()
            {
                while (true)
                {
                    IPAddress myipAddress = Dns.GetHostAddresses(Dns.GetHostName())[0];
                    IPEndPoint localEndPoint = new IPEndPoint(myipAddress, listenport);
                    _svrSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    try
                    {
                        _svrSock.Bind(localEndPoint);
                        _svrSock.Listen(100);
                        _svrSock.BeginAccept(new AsyncCallback(AcceptCallback), _svrSock);
                    }
                    catch { }
                }
            }        public void AcceptCallback(IAsyncResult ar)
            {
                //Done.Set();
                try
                {
                    Socket serverSock = (Socket)ar.AsyncState;
                    Socket clientSock = serverSock.EndAccept(ar);
                    state = new StateObject();
                    state.workSocket = clientSock;                byte[] bytedata = System.Text.Encoding.BigEndianUnicode.GetBytes("1");
                    clientSock.BeginSend(bytedata, 0, bytedata.Length, 0, new AsyncCallback(SendCallback), clientSock);                clientSock.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
                }
                catch (Exception ex){MessageBox.Show(ex.Message, "服务器提示");}
            }        public void SendCallback(IAsyncResult ar)
            {
                try
                {
                    Socket clientSocket = (Socket)ar.AsyncState;
                    int bytesSent = clientSocket.EndSend(ar);
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.Message);
                }
            }        public void ReadCallback(IAsyncResult ar)
            {
                StateObject state = (StateObject)ar.AsyncState;
                Socket clientSocket = state.workSocket;
                int bytesRead = clientSocket.EndReceive(ar);
                string strF = System.Text.Encoding.BigEndianUnicode.GetString(state.buffer,0,bytesRead);
                string[] tokens = strF.Split(new char[] { '|' });
                string before = tokens[1];
                string after = Regex.Replace(tokens[1], "[0-9.]", "");
                tokens[1] = tokens[1].Substring(0, before.Length - after.Length);            if (bytesRead == 0)
                {
                    return;
                }
                else
                {
                    try
                    {//下面是根据客户端发的消息对其作出在线或不在线的处理
                        if (tokens[0].ToString() == "CONN")
                        {
                            for (int i = 0; i < lstClients.Items.Count; i++)
                            {
                                Machines machine = (Machines)lstClients.Items[i];
                                if (machine.Ip == tokens[1] && machine.ImgSource == "Images/ComputerGray.png")
                                {
                                    machine.ImgSource = "Images/ComputerLight.png";
                                    list.Add(clientSocket);
                                    clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
                                    break;
                                }
                            }
                            Dispatcher.Invoke((SetListView)delegate { SetRefresh(); }, new object[] { });
                        }
                        else if (tokens[0].ToString() == "GONE")
                        {
                            for (int i = 0; i < lstClients.Items.Count; i++)
                            {
                                Machines machine = (Machines)lstClients.Items[i];
                                if (machine.Ip == tokens[1] && machine.ImgSource == "Images/ComputerLight.png")
                                {
                                    machine.ImgSource = "Images/ComputerGray.png";
                                    list.Remove(clientSocket);
                                    break;
                                }
                            }
                            Dispatcher.Invoke((SetListView)delegate { SetRefresh(); }, new object[] { });
                            clientSocket.Close();
                        }
                        else
                        {
                            for (int i = 0; i < lstClients.Items.Count; i++)
                            {
                                Machines machine = (Machines)lstClients.Items[i];
                                if (machine.Ip == tokens[1] && machine.ImgSource == "Images/ComputerLight.png")
                                {
                                    machine.ImgSource = "Images/ComputerGray.png";
                                    list.Remove(clientSocket);
                                    break;
                                }
                            }
                            Dispatcher.Invoke((SetListView)delegate { SetRefresh(); }, new object[] { });
                            clientSocket.Close();
                        }
                    }
                    catch (Exception ee){MessageBox.Show(ee.Message);}
                }
            }        //线程调用控件
            private void SetRefresh()
            {
                lstClients.Items.Refresh();
                SortList();
            }        //排序用户,图片高亮的显示在前
            private void SortList()
            {
                ICollectionView view = GetView();
                view.SortDescriptions.Add(new SortDescription("ImgSource", ListSortDirection.Descending));
            }        public class StateObject
            {
                public Socket workSocket = null;
                public const int BufferSize = 64 * 1024;
                public byte[] buffer = new byte[BufferSize];
                public int isOnLine;//2表示在线,1,0表示不在线;
            }        //获取Listview数据源的视图
            ICollectionView GetView()
            {
                return CollectionViewSource.GetDefaultView(_machineItem);
            }
        }
    }
      

  6.   

    客户端代码:
    namespace WindowsClient1
    {
        public partial class Form1 : Form
        {
            private StateObject state;
            private delegate void SetTextCallBack(string str);        private System.ComponentModel.IContainer components = null;        /// <summary>
            /// 清理所有正在使用的资源。
            /// </summary>
            /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing)
                {
                    if (components != null)
                    {
                        components.Dispose();
                    }
                }
                base.Dispose(disposing);
            }        private void Form1_Load(object sender, EventArgs e)
            {
                try
                {
                    IPAddress ipAddress = Dns.GetHostAddresses(Dns.GetHostName())[0];
                    IPEndPoint remoteEP = new IPEndPoint(ipAddress, 5555);
                    Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    
                    clientSocket.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), clientSocket);
                }
                catch (Exception ee)
                {
                    MessageBox.Show(ee.Message, "客户端提示");
                }        }        private void ConnectCallback(IAsyncResult ar)
            {
                try
                {
                    Socket clientSock = (Socket)ar.AsyncState;
                    clientSock.EndConnect(ar);
                    state = new StateObject();
                    state.workSocket = clientSock;
                    string data = "CONN|" + Dns.GetHostAddresses(Dns.GetHostName())[0].ToString();
                    byte[] byteData = System.Text.Encoding.BigEndianUnicode.GetBytes(data);
                    clientSock.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), clientSock);
                    clientSock.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
                }
                catch (Exception ee) { MessageBox.Show(ee.Message, "客户端提示"); }
            }        private void SetText(string str)
            {
                if (richTextBox3.InvokeRequired)
                {
                    SetTextCallBack st = new SetTextCallBack(SetText);
                    this.Invoke(st, new object[] { str });
                }
                else
                    richTextBox3.AppendText(str);
            }        private void ReadCallback(IAsyncResult ai)
            {
                try
                {
                    StateObject state = (StateObject)ai.AsyncState;
                    Socket client = state.workSocket;
                    int byteread = client.EndReceive(ai);
                    string strF = System.Text.Encoding.BigEndianUnicode.GetString(state.buffer, 0, byteread);
                    if (strF != "")
                    {
                        SetText("来自服务器的消息:" + strF);
                    }
                    client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
                }
                catch (Exception ee) { MessageBox.Show(ee.Message, "客户端提示"); }
            }        private void SendCallback(IAsyncResult ar)
            {
                try
                {
                    Socket clientSocket = (Socket)ar.AsyncState;
                    int bytesSent = clientSocket.EndSend(ar);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "客户端提示");
                }
            }        public class StateObject
            {
                public Socket workSocket = null;
                public const int BufferSize = 64 * 1024;
                public byte[] buffer = new byte[BufferSize];
                public int isOnLine;//2表示在线,1,0表示不在线;
            }        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                try
                {
                    Socket closesocket = (Socket)state.workSocket;
                    string data = "GONE|" + Dns.GetHostAddresses(Dns.GetHostName())[0].ToString();
                    byte[] byteData = System.Text.Encoding.BigEndianUnicode.GetBytes(data);
                    closesocket.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), closesocket);
                    closesocket.Shutdown(SocketShutdown.Both);
                    closesocket.Close();
                }
                catch { }
            }
        }
    }
      

  7.   


    我想问一下。如果客户端程序是一直运行的,服务器端的是不定时被打开的。我的服务器端程序可不可以这样做:服务器端程序启动后,由服务器向客户端发个字符串,服务器接收,并这个字符串在发给服务器,服务器判断有没有受到客户端发来的消息判断客户端是否在线。用个timer控制定时发消息给客户端,以保证实时的现实在线的客户端。不知道我这样想的合适吗?
      

  8.   


    思路上就错误了。始终运行着的那一端,才适合做Socket服务端。会被反复打开、关闭的那一端,才适合做Socket客户端。业务意义上的服务端和客户端,不一定非得对应Socket的服务端和客户端。你这个问题改用上述思路考虑一下,不就非常简单了吗?服务端启动后,启动Socket客户端,尝试连接Socket服务端(即业务上的客户端),连接成功后,Socket服务端在该连接上发送身份标识数据过去,不就完成业务登录了吗?
      

  9.   


    请问,如果业务上的客户端有多个也是由他了充当socket服务器吗?
      

  10.   

    1、多个客户端也一样,不要于2000个一般都没问题
    2、“远程主机强迫关闭了一个现有的链接” 说明创建的Socket链接没有正确的关闭
      

  11.   

    “远程主机强迫关闭了一个现有的链接” 说明创建的Socket链接没有正确的关闭
      

  12.   

    这些问题实在看来蛋疼,楼主就不能稍微先看看socket编程的一些基础知识再开始写程序么?就算不想看,莫非google和baidu不出来?
      

  13.   

    http://topic.csdn.net/u/20080623/08/4bbd2475-45f1-42e3-a613-16b094759ade.html