无论客户端发生什么情况,如何让服务器程序保持 运行?
How can I make a server program keep running no matter what happens to a client?
看看下面两个程序:
//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();
}
}
}
}
我遇到的服务器问题是,客户端一关闭,服务器程序就退出了。
我希望服务器程序保持 运行 无论客户端做什么或发生什么。
我该怎么做?
尝试围绕您的 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
请注意,这是非常不安全的 - 任何客户端,无论他们在哪里/是谁,都可以终止您的服务器向您的服务器发送 "quit" 消息。在现实生活中,您可能需要更严格的机制。显然,使用这种机制,您将需要您的客户端能够在需要时生成 "quit" 消息文本。
另一种方法是运行整个服务器在一个线程中。然后在另一个线程中,有一个操作员可以用来关闭服务器的方法(例如,Swing 应用程序中的菜单选择)。
您可以选择很多选项来 "manage" 关机。
此外,正如所写,您的代码是单线程的。也就是说,它将等待客户端连接,处理该客户端然后退出(或者如果您应用 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.
}
}
}
看看下面两个程序:
//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();
}
}
}
}
我遇到的服务器问题是,客户端一关闭,服务器程序就退出了。
我希望服务器程序保持 运行 无论客户端做什么或发生什么。
我该怎么做?
尝试围绕您的 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
请注意,这是非常不安全的 - 任何客户端,无论他们在哪里/是谁,都可以终止您的服务器向您的服务器发送 "quit" 消息。在现实生活中,您可能需要更严格的机制。显然,使用这种机制,您将需要您的客户端能够在需要时生成 "quit" 消息文本。
另一种方法是运行整个服务器在一个线程中。然后在另一个线程中,有一个操作员可以用来关闭服务器的方法(例如,Swing 应用程序中的菜单选择)。
您可以选择很多选项来 "manage" 关机。
此外,正如所写,您的代码是单线程的。也就是说,它将等待客户端连接,处理该客户端然后退出(或者如果您应用 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.
}
}
}