C#服务器程序无法检测到断开的链接

时间:2019-05-28 10:46:52

标签: c# tcp client-server tcpclient

以下是.net服务器和Java客户端程序的基本框架:

C# server skeleton

class ServerProgram
{
    static string origClientID = string.Empty;
    static string reqClientID = string.Empty;
    static string stKey = string.Empty;
    static string stValue = string.Empty;
    static Dictionary<string, KeyValue> KeyValueDictionary;
    static Dictionary<string, ClientClass> ClientDictionary;

    static void Main(string[] args)
    {
        Console.Title = "Server";
        Console.WriteLine("Server program started on address [" + Constants.SERVER_IP +":"+Constants.PORT_NO+"]");

        KeyValueDictionary = new Dictionary<string, KeyValue>();
        ClientDictionary = new Dictionary<string, ClientClass>();

        string ipAddress = Constants.SERVER_IP;
        int portNo = Constants.PORT_NO;

        IPAddress ip = IPAddress.Parse(ipAddress);            
        TcpListener listener = new TcpListener(ip, portNo);            

        // poll for clients in a 2nd thread
        Thread thread = new Thread(delegate()
        {
            ServerProgram.PollIncomingClientConns(listener);
        });

        thread.Start();
    }

    #region catching client connections
    static void PollIncomingClientConns(TcpListener listener)
    {
        listener.Start();

        try
        {
            bool keepRunning = true;

            while (keepRunning)
            {
                ClientClass client = new ClientClass(listener);

                ClientDictionary.Add(client.ID, client);

                Thread thread = new Thread(delegate()
                {
                    ServerProgram.ReadFromClient(client);
                });
                thread.Start();
            }
        }
        catch (Exception ex)
        {
            var inner = ex.InnerException as SocketException;
            if (inner != null && inner.SocketErrorCode == SocketError.ConnectionReset)
                Console.WriteLine("Disconnected");
            else
                Console.WriteLine(ex.Message);

            listener.Stop();
        }
    } 
    #endregion     

    static void ReadFromClient(ClientClass client)
    {
       try
        {
            while (client.Tcp.Connected)
            {
                string str = client.Read();
                Console.WriteLine("[" + client.ID + "] says: " + str);

                switch(str)
                {
                    case Commands.AddKeyValue:
                        //...                        
                        break;

                    case Commands.ListKeys:
                        //...
                        break;

                    case Commands.UpdateValue: 
                        //...
                        break;

                    case Commands.Yes:                            
                        //...
                        break;
                }
            }
        }
        catch
        {
            client.Disconnect();
        }
    }
}

Java Client skeleton

public class FirstJavaClientProgramTest  
{ 
    final static String LOCAL_HOST = "127.0.0.1";
    final static int PORT_NO = 4321; 

    public static void main(String args[]) throws UnknownHostException, IOException  
    { 
        try
        {
            Consolas.WriteLine("Hit enter twice to connect to localhost...\n");

            Consolas.WriteLine("Enter server IP : ");
            String ip = Consolas.ReadLine();

            Consolas.WriteLine("Enter server port : ");
            String portStr = Consolas.ReadLine();

            int port = -99;
            if(ip.equals("\n") || ip.equals("")) 
            {
                ip = LOCAL_HOST;
            } 

            if(!ip.equals("\n") || !ip.equals(""))
            { 
                port = PORT_NO;
            }
            else 
            {
                port = Integer.parseInt(portStr);
            }

            // establish the connection 
            Socket socket = new Socket(ip, port); 

            //send the client ID
            String ID = AlphaNumRandom.randomString(5);
            Consolas.WriteLine(ID);

            BinaryWriter writer = new BinaryWriter(socket);
            writer.Write(ID);

            ReaderRunnableClass readRunnable = new ReaderRunnableClass(socket);        
            Thread readThread = new Thread(readRunnable);        
            readThread.start();

            WriterRunnableClass writeRunnable = new WriterRunnableClass(socket);        
            Thread writeThread = new Thread(writeRunnable);        
            writeThread.start();
        }
        catch(Exception ex)
        {
            Consolas.WriteLine("Failed to connect to the server!");
            //Consoles.WriteLine(ex.getMessage());
        }
    }//:~ main
}//:~ class

服务器程序有问题。

如果客户端被用户明确关闭,则服务器程序可以检测到客户端断开连接。

但是,服务器程序无法明确检测

  1. 如果客户端崩溃了,和/或
  2. 如果通信过程中网络链接失败

我该如何检测?

2 个答案:

答案 0 :(得分:0)

您应该定期向所有连接的客户端发送保持活动消息。查看本文Detection of Half-Open (Dropped) Connections。实际上,我建议您阅读整个系列TCP/IP .NET Sockets FAQHere,您可以使用KeepAlive方法检查C#实现的示例。

答案 1 :(得分:-1)

我认为您必须创建一个遍历ClientDictionary的方法,以检查客户端连接是否仍然有效。在这里看看:Instantly detect client disconnection from server socket