我目前正在使用c#.net Windows窗体开发TCP侦听器。一段时间后,当客户端随后发出不监听的请求时,它似乎停止监听。没有异常。
namespace WindowsTCPListener
{
public partial class Form1 : Form
{
TcpListener listener;
public Form1()
{
InitializeComponent();
Thread t = new Thread(() =>
{
ListenTCPPort();
});
t.Start();
}
public void ListenTCPPort()
{
string ipAddress, portNumber, mqName;
ipAddress = ConfigurationManager.AppSettings.Get("IP").ToString().Trim();
portNumber = ConfigurationManager.AppSettings.Get("PORT").ToString().Trim();
mqName = ConfigurationManager.AppSettings.Get("MSMQ").ToString().Trim();
int j;
int port = Int32.TryParse(portNumber, out j) ? j : 0;
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ipAddress.ToString()), port);
listener = new TcpListener(ep);
listener.Start();
try
{
this.listBox1.Items.Add("Started listening requests at: " + ipAddress.ToString() + ":" + portNumber.ToString());
}
catch (Exception) {}
while (true)
{
try
{
const int bytesize = 1024 * 1024;
string message = null;
byte[] buffer = new byte[bytesize];
TcpClient sender = listener.AcceptTcpClient();
sender.GetStream().Read(buffer, 0, bytesize);
message = cleanMessage(buffer);
byte[] bytes = System.Text.Encoding.Default.GetBytes(message);
string data = System.Text.Encoding.Default.GetString(bytes);
try
{
this.listBox1.Items.Add("Incoming : " + data.ToString());
}
catch (Exception) {}
string output = sendMessage(data, sender, mqName);
this.listBox1.Items.Add(output);
sender.Close();
}
catch (Exception e)
{
try
{
this.listBox1.Items.Add("Exception : " + e.ToString());
}
catch (Exception) { }
}
}
}
}
}
答案 0 :(得分:0)
您的代码不完整,因此答案不完整:)
我已经重构了您的代码,以便正确处理UI:禁止从其他线程与UI进行交互。 这样做的行为是设计不确定的,因此其他所有后果都可能会导致。
当您必须访问UI时,必须询问控件(或窗体)是否可以直接直接访问它:在InvokeRequired == false
时是安全的。
这是您重构的摘录:它适用于多个后续(非当代)连接。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp3
{
public partial class Form1 : Form
{
private TcpListener listener;
private delegate void StringVoidInvoker(string value);
public Form1()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// it is better to start your thread when the UI controls are just one step away from being created
Thread t = new Thread(() =>
{
ListenTCPPort();
});
// this way, closing the form closes the thread. this is a bad practice, since you should be using a more reliable method to close the thread (e.g. events and waithandles)
t.IsBackground = true;
t.Start();
}
private void SafeLog(string value)
{
if (this.InvokeRequired)
{
// if we are being called between threads, we have to ask the original UI thread to perfom the task
this.Invoke(new StringVoidInvoker(SafeLog), new object[] { value });
}
else
{
this.listBox1.Items.Add(value);
}
}
public void ListenTCPPort()
{
string ipAddress, portNumber, mqName;
ipAddress = ConfigurationManager.AppSettings.Get("IP").ToString().Trim();
portNumber = ConfigurationManager.AppSettings.Get("PORT").ToString().Trim();
mqName = ConfigurationManager.AppSettings.Get("MSMQ").ToString().Trim();
int j;
int port = Int32.TryParse(portNumber, out j) ? j : 0;
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ipAddress.ToString()), port);
listener = new TcpListener(ep);
listener.Start();
SafeLog("Started listening requests at: " + ipAddress.ToString() + ":" + portNumber.ToString());
while (true)
{
try
{
const int bytesize = 1024 * 1024;
string message = null;
byte[] buffer = new byte[bytesize];
TcpClient sender = listener.AcceptTcpClient();
sender.GetStream().Read(buffer, 0, bytesize);
message = cleanMessage(buffer);
byte[] bytes = System.Text.Encoding.Default.GetBytes(message);
string data = System.Text.Encoding.Default.GetString(bytes);
SafeLog("Incoming : " + data.ToString());
string output = sendMessage(data, sender, mqName);
SafeLog(output);
sender.Close();
}
catch (Exception e)
{
SafeLog("Exception : " + e.ToString());
}
}
}
private string sendMessage(string data, TcpClient sender, string mqName)
{
// place here your logic
return "NOTIMPL";
}
private string cleanMessage(byte[] buffer)
{
// place here your logic
return "NOTIMPL";
}
}
}
请参阅上面代码中的注释。
罪魁祸首以正确的方式访问UI:
private void SafeLog(string value)
{
if (this.InvokeRequired)
{
// if we are being called between threads, we have to ask the original UI thread to perfom the task
this.Invoke(new StringVoidInvoker(SafeLog), new object[] { value });
}
else
{
this.listBox1.Items.Add(value);
}
}
答案 1 :(得分:0)
sender.GetStream().Read
实际上阻止了该方法,它一直等到有传入数据时,因此您的代码一次只能处理一个连接。您应该将读取的代码放在另一个线程中。