【问题标题】:How can I make a server program keep running no matter what happens to a client?无论客户端发生什么,如何使服务器程序继续运行?
【发布时间】:2019-04-28 17:56:23
【问题描述】:

看看下面两个程序:

//Server

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace MyServerProgram
{
    class Program
    {
        static void Main(string[] args)
        {            
            IPAddress ip = IPAddress.Parse("127.0.0.1");
            int port = 2000;
            TcpListener listener = new TcpListener(ip, port);
            listener.Start();

            TcpClient client = listener.AcceptTcpClient();
            Console.WriteLine("Connected " + ((IPEndPoint)client.Client.RemoteEndPoint).Address);


            NetworkStream netStream = client.GetStream();

            BinaryReader br = new BinaryReader(netStream);

            try
            {
                while (client.Client.Connected)
                {
                    string str = br.ReadString();

                    Console.WriteLine(str);
                }
            }
            catch (Exception ex)
            {
                var inner = ex.InnerException as SocketException;
                if (inner != null && inner.SocketErrorCode == SocketError.ConnectionReset)
                    Console.WriteLine("Disconnected");
                else
                    Console.WriteLine(ex.Message);

                br.Close();
                netStream.Close();
                client.Close();
                listener.Stop();
            }
        }
    }
}


//Client

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace MyClientProgram
{
    class Program
    {
        static void Main(string[] args)
        {
            int port = 2000;
            TcpClient client = new TcpClient("localhost", port);

            NetworkStream netStream = client.GetStream();

            BinaryWriter br = new BinaryWriter(netStream);

            try
            {
                int i=1;
                while (client.Client.Connected)
                {
                    br.Write(i.ToString());
                    br.Flush();
                    i++;

                    int milliseconds = 2000;
                    System.Threading.Thread.Sleep(milliseconds);
                }
            }
            catch
            {
                br.Close();
                netStream.Close();
                client.Close();
            }
        }
    }
}

我面临的服务器问题是,一旦客户端关闭,服务器程序就会退出。

无论客户端做什么或发生什么,我都希望服务器程序继续运行。

我该怎么做?

【问题讨论】:

  • 带有while(true) 循环。
  • @HenkHolterman,好的。但是,那么如何打破循环呢?
  • 时机成熟时使用break;

标签: c# tcp tcpclient tcplistener


【解决方案1】:

尝试在您的 AcceptTcpClient(和相关逻辑)周围放置一个 while 循环。 套用您的服务器代码:

boolean keepRunning = true;
while (keepRunning) {
  TcpClient client = listener.AcceptTcpClient();
  Console.WriteLine("Connected ...") // and other stuff deleted.

  // while client connected...
      string str = br.ReadString();
      // check to see if we should continue running.
      keepRunning = ! "quit".equalsIgnoreCase(str);
  // Other stuff

请注意,这是非常不安全的 - 任何客户端,无论他们在哪里/谁都可以终止您的服务器,向您的服务器发送“退出”消息。在现实生活中,您可能需要更严格的机制。显然,使用这种机制,您将需要您的客户端能够在需要时生成“退出”消息文本。

另一种方法是在一个线程中运行整个服务器。然后在另一个线程中,有一个操作员可以用来关闭服务器的方法(例如 Swing 应用程序中的菜单选择)。

您可以选择很多选项来“管理”关机。

另外,正如所写,您的代码是单线程的。也就是说,它将等待客户端连接,处理该客户端然后退出(或者如果您应用 keepRunning while 循环修改等待下一个客户端连接)。但是,任何时候只有一个客户端可以连接到这个服务器。

要使其成为多线程(一次可以为多个客户端提供服务),请将您的服务器主体(服务代码)放入一个 Thread 并调用 Thread 的一个新实例来为该客户端提供服务。启动服务线程后,主循环只是等待下一个客户端连接。 因此,你的主循环会变成这样:

while (keepRunning) {
    TcpClient client = listener.AcceptTcpClient();
    Console.WriteLine("Connected ...") // and other stuff deleted.

    ServiceThread st = new ServiceThread(client);
    st.start ();
}

服务线程将类似于:

public class ServiceThread extends Thread {
  private TcpClient client;
  public ServiceThread (TcpClient client) {
    this.client = client;
  }
  @override
  public void run() {
    NetworkStream netStream = client.GetStream();
    BinaryReader br = new BinaryReader(netStream);
    try {
            while (client.Client.Connected) {
            // Stuff deleted for clarity
            }
         }
        catch (Exception ex) {
            // Exception handling stuff deleted for clarity.
        }
  }
}

【讨论】:

  • 哦,您可能会考虑的另一件事是将“服务器的服务”代码放入线程中。这就是“AcceptTcpClient”应该进入线程之后的所有内容。按照目前的写法,任何时候只能处理一个客户端。如果您将“服务”代码放入线程中,您的主线程只是返回等待下一个客户端连接,而单独的线程同时处理客户端请求。只是一个想法....
  • 请把您的评论放在答案的主体上并总结一下,因为此时我对您实际上试图暗示的线程技术感到困惑。服务代码是什么意思?
猜你喜欢
  • 1970-01-01
  • 2016-08-26
  • 2019-07-12
  • 1970-01-01
  • 2019-06-03
  • 1970-01-01
  • 2015-08-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多