具有套接字连接的后台 运行 服务器
Background running server with socket connection
现在我有了这个:
[STAThread]
static void Main()
{
if (flag) //client view
Application.Run(new Main_Menu());
else
{
Application.Run(new ServerForm());
}
}
ServerForm.cs
public partial class ServerForm : Form
{
public ServerForm()
{
InitializeComponent();
BeginListening(logBox);
}
public void addLog(string msg)
{
this.logBox.Items.Add(msg);
}
private void button1_Click(object sender, EventArgs e)
{
}
private async void BeginListening(ListBox lv)
{
Server s = new Server(lv);
s.Start();
}
}
Server.cs
public class Server
{
ManualResetEvent allDone = new ManualResetEvent(false);
ListBox logs;
///
///
/// Starts a server that listens to connections
///
public Server(ListBox lb)
{
logs = lb;
}
public void Start()
{
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(new IPEndPoint(IPAddress.Loopback, 1440));
while (true)
{
Console.Out.WriteLine("Waiting for connection...");
allDone.Reset();
listener.Listen(100);
listener.BeginAccept(Accept, listener);
allDone.WaitOne(); //halts this thread
}
}
//other methods like Send, Receive etc.
}
我想 运行 我的 ServerForm
(它有 ListBox 可以打印来自 Server
的消息)。我知道 ListBox
参数不起作用,但我无法 运行 Server
无限循环而不暂停 ServerForm
(我什至无法移动 window)。我也用 Threads 尝试过 - 不幸的是它不起作用。
WinForms 有一个叫做 UI-thread 的东西。它是一个线程,负责绘制和处理 UI。如果该线程正忙于做某事,UI 将停止响应。
常规套接字方法是阻塞的。这意味着它们不会 return 控制您的应用程序,除非套接字上发生了某些事情。因此,每次在 UI 线程上执行套接字操作时,UI 将停止响应,直到套接字方法完成。
要解决这个问题,您需要为套接字操作创建一个单独的线程。
public class Server
{
ManualResetEvent allDone = new ManualResetEvent(false);
Thread _socketThread;
ListBox logs;
public Server(ListBox lb)
{
logs = lb;
}
public void Start()
{
_socketThread = new Thread(SocketThreadFunc);
_socketThread.Start();
}
public void SocketThreadFunc(object state)
{
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(new IPEndPoint(IPAddress.Loopback, 1440));
while (true)
{
Console.Out.WriteLine("Waiting for connection...");
allDone.Reset();
listener.Listen(100);
listener.BeginAccept(Accept, listener);
allDone.WaitOne(); //halts this thread
}
}
//other methods like Send, Receive etc.
}
但是,所有 UI 操作必须在 UI 线程上进行。这一点,如果您尝试从套接字线程更新 listbox
,您将得到一个异常。
最简单的解决方法是使用 Invoke.
现在我有了这个:
[STAThread]
static void Main()
{
if (flag) //client view
Application.Run(new Main_Menu());
else
{
Application.Run(new ServerForm());
}
}
ServerForm.cs
public partial class ServerForm : Form
{
public ServerForm()
{
InitializeComponent();
BeginListening(logBox);
}
public void addLog(string msg)
{
this.logBox.Items.Add(msg);
}
private void button1_Click(object sender, EventArgs e)
{
}
private async void BeginListening(ListBox lv)
{
Server s = new Server(lv);
s.Start();
}
}
Server.cs
public class Server
{
ManualResetEvent allDone = new ManualResetEvent(false);
ListBox logs;
///
///
/// Starts a server that listens to connections
///
public Server(ListBox lb)
{
logs = lb;
}
public void Start()
{
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(new IPEndPoint(IPAddress.Loopback, 1440));
while (true)
{
Console.Out.WriteLine("Waiting for connection...");
allDone.Reset();
listener.Listen(100);
listener.BeginAccept(Accept, listener);
allDone.WaitOne(); //halts this thread
}
}
//other methods like Send, Receive etc.
}
我想 运行 我的 ServerForm
(它有 ListBox 可以打印来自 Server
的消息)。我知道 ListBox
参数不起作用,但我无法 运行 Server
无限循环而不暂停 ServerForm
(我什至无法移动 window)。我也用 Threads 尝试过 - 不幸的是它不起作用。
WinForms 有一个叫做 UI-thread 的东西。它是一个线程,负责绘制和处理 UI。如果该线程正忙于做某事,UI 将停止响应。
常规套接字方法是阻塞的。这意味着它们不会 return 控制您的应用程序,除非套接字上发生了某些事情。因此,每次在 UI 线程上执行套接字操作时,UI 将停止响应,直到套接字方法完成。
要解决这个问题,您需要为套接字操作创建一个单独的线程。
public class Server
{
ManualResetEvent allDone = new ManualResetEvent(false);
Thread _socketThread;
ListBox logs;
public Server(ListBox lb)
{
logs = lb;
}
public void Start()
{
_socketThread = new Thread(SocketThreadFunc);
_socketThread.Start();
}
public void SocketThreadFunc(object state)
{
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(new IPEndPoint(IPAddress.Loopback, 1440));
while (true)
{
Console.Out.WriteLine("Waiting for connection...");
allDone.Reset();
listener.Listen(100);
listener.BeginAccept(Accept, listener);
allDone.WaitOne(); //halts this thread
}
}
//other methods like Send, Receive etc.
}
但是,所有 UI 操作必须在 UI 线程上进行。这一点,如果您尝试从套接字线程更新 listbox
,您将得到一个异常。
最简单的解决方法是使用 Invoke.