问题
I am trying to learn TCP server/client interaction. I want to know how I would listen to a port all the time with GUI. Currently I am using this code:
private void Form1_Load(object sender, EventArgs e)
{
CreateServer();
}
void CreateServer()
{
TcpListener tcp = new TcpListener(25565);
tcp.Start();
Thread t = new Thread(() =>
{
while (true)
{
var tcpClient = tcp.AcceptTcpClient();
ThreadPool.QueueUserWorkItem((_) =>
{
Socket s = tcp.AcceptSocket();
console.Invoke((MethodInvoker)delegate { console.Text += "Connection esatblished: " + s.RemoteEndPoint + Environment.NewLine; });
byte[] b = new byte[100];
int k = s.Receive(b);
for (int i = 0; i < k; i++)
{
console.Text += Convert.ToChar(b[i]);
incoming += Convert.ToChar(b[i]);
}
MessageBox.Show(incoming);
console.Invoke((MethodInvoker)delegate { console.Text += incoming + Environment.NewLine; });
list.Invoke((MethodInvoker)delegate { list.Items.Add(incoming); });
ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes("\n"));
tcpClient.Close();
}, null);
}
});
t.IsBackground = true;
t.Start();
}
Any help would be much appreciateed.
回答1:
Short answer - run TCP listener in the separate Thread/Task (TPL). For full working solution you also have to implement dispatching of the any changes to UI form separate thread to main thread using special technique which is depends on Framework you are using, I mean WPF/WinForms/whatever.
Code below works for me fine. Read TODO section before.
TODO:
Add to form Textbox, ListBox, Button, make public:
public System.Windows.Forms.TextBox console; public System.Windows.Forms.ListBox incommingMessages; private System.Windows.Forms.Button sendSampleDataButton;
Entry point:
private static Form1 form;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
form = new Form1();
form.Load += OnFormLoad;
Application.Run(form);
}
private static void OnFormLoad(object sender, EventArgs e)
{
CreateServer();
}
Server:
private static void CreateServer()
{
var tcp = new TcpListener(IPAddress.Any, 25565);
tcp.Start();
var listeningThread = new Thread(() =>
{
while (true)
{
var tcpClient = tcp.AcceptTcpClient();
ThreadPool.QueueUserWorkItem(param =>
{
NetworkStream stream = tcpClient.GetStream();
string incomming;
byte[] bytes = new byte[1024];
int i = stream.Read(bytes, 0, bytes.Length);
incomming = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
form.console.Invoke(
(MethodInvoker)delegate
{
form.console.Text += String.Format(
"{0} Connection esatblished: {1}{2}",
DateTime.Now,
tcpClient.Client.RemoteEndPoint,
Environment.NewLine);
});
MessageBox.Show(String.Format("Received: {0}", incomming));
form.incommingMessages.Invoke((MethodInvoker)(() => form.incommingMessages.Items.Add(incomming)));
tcpClient.Close();
}, null);
}
});
listeningThread.IsBackground = true;
listeningThread.Start();
}
Client
private void button1_Click(object sender, EventArgs e)
{
Connect("localhost", "hello localhost " + Guid.NewGuid());
}
static void Connect(String server, String message)
{
try
{
Int32 port = 25565;
TcpClient client = new TcpClient(server, port);
Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
NetworkStream stream = client.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
stream.Close();
client.Close();
}
catch (ArgumentNullException e)
{
Debug.WriteLine("ArgumentNullException: {0}", e);
}
catch (SocketException e)
{
Debug.WriteLine("SocketException: {0}", e);
}
}
Screenshot:
回答2:
Create a thread, start to listen in it & don't stop the server
void CreateServer()
{
TcpListener tcp = new TcpListener(25565);
tcp.Start();
Thread t = new Thread(()=>
{
while (true)
{
var tcpClient = tcp.AcceptTcpClient();
ThreadPool.QueueUserWorkItem((_) =>
{
//Your server codes handling client's request.
//Don't access UI control directly here
//Use "Invoke" instead.
tcpClient.Close();
},null);
}
});
t.IsBackground = true;
t.Start();
}
回答3:
You could use the threads approach (as mentioned by other answers) or use asynchronous sockets, which in my opnion is way better. And even better, you can use the async model proposed by SocketAsyncEventArgs. Async sockets will take benefits from using completion ports.
回答4:
here is a good example on mdsn: Asynchronous server socket example
来源:https://stackoverflow.com/questions/9533013/how-would-i-constant-listen-on-a-port-with-a-gui