【发布时间】:2019-04-24 08:52:33
【问题描述】:
我正在尝试制作一个简单的服务器应用程序来学习 C# 中多线程服务器编程的基础知识。基本思想很简单:客户端连接到服务器并发送:“get time”来接收服务器的当前时间。所有 tcplistener 线程和套接字都应该在单独的线程上运行。我不知道为什么,但是当应用程序完成所有线程的初始化时,控制台应用程序就会关闭。
这是服务器代码:
class Program
{
static public int minPort;
static public int maxPort;
static int openPort = 0;
static byte[] sendData = new byte[1024];
static TcpListener[] listeners;
static Thread[] connectionThreads;
static void Main()
{
Console.Write("What do you want your minimum port to be? ");
minPort = Convert.ToInt32(Console.ReadLine());
Console.Write("What do you want your maximum port to be? ");
maxPort = Convert.ToInt32(Console.ReadLine());
//init
ThreadStart streamThreadStart = new ThreadStart(DataStream);
openPort = maxPort - minPort;
listeners = new TcpListener[maxPort - minPort];
connectionThreads = new Thread[maxPort - minPort];
for (int i = 0; i == maxPort - minPort; i++)
{
listeners[i] = new TcpListener(IPAddress.Any, minPort + i);
connectionThreads[i] = new Thread(streamThreadStart);
Thread.Sleep(10);
openPort = openPort + 1;
}
}
static void DataStream()
{
int port = openPort;
byte[] receiveData = new byte[1024];
listeners[openPort].Start();
Socket socket = listeners[port].AcceptSocket();
NetworkStream stream = new NetworkStream(socket);
while (true)
{
socket.Receive(receiveData);
Console.WriteLine("Received: " + BitConverter.ToString(receiveData));
socket.Send(parseCommand(receiveData));
}
}
static byte[] parseCommand(byte[] input)
{
string RCommand = BitConverter.ToString(input);
string SCommand;
if (RCommand == "get time")
{
SCommand = DateTime.Now.ToUniversalTime().ToString();
}else
{
SCommand = "Unknown Command, please try again";
}
byte[] output = Encoding.ASCII.GetBytes(SCommand);
return output;
}
}
【问题讨论】:
-
在控制台应用程序中,当 main 完成时,应用程序将关闭,因为没有更多代码可以执行。您需要在 main 中构建一个循环以保持控制台应用程序运行。
-
您知道一个侦听器套接字可以服务多个客户端并移交接受的套接字吗?除非您正在做一些非常奇怪的事情,否则永远不需要在多个端口上运行侦听器。例如。普通的 Web 服务器只监听端口 80 和/或 443。你认为这些处理数千个客户端的服务器一次只处理一个客户端吗?这里需要大量的研究/阅读。
-
另外,您必须注意来自
Receive的返回值和道德等价物。因为 TCP 给你的只是一个字节流,而不是消息。它不保证会填满您的缓冲区,或者您将收到的内容与传递给另一端Send的单个调用的单个缓冲区匹配。 -
另一种选择是创建一个Windows Service,它旨在长期运行而不关闭。
标签: c# .net multithreading sockets console-application