嘿伙计们我一直在努力学习如何使用TcpListener和套接字在客户端服务器之间发送一些简单的文本消息。我已经阅读了许多线程,这些线程似乎显示了如何读取_Buffer,让我们说一个循环以确保读取整个消息。但是,我似乎无法弄清楚如何在收到第一条消息后获取第二条消息。我可以很好地连接到服务器,我可以得到第一条消息。但是,如果我再次点击我的客户端上的发送按钮,则没有消息到达服务器。这是我的代码:
// SERVER APPLICATION: -----------------------------------------------namespace TCP_Server { public partial class Form1 : Form { public Form1() { InitializeComponent(); }
private void btnStartServer_Click(object sender, EventArgs e) { // Define the TCP Listner: TcpListener _listner = new TcpListener(IPAddress.Parse("127.0.0.1"), 7777); // Start The Listner: _listner.Start(); //Show the server is now listening: listStatus.Items.Add("Server started - Listening on port 7777"); //Create a socket to accept - This is a Blocking Call: Socket _sock = _listner.AcceptSocket(); //When Client Connects show server has accepted the socket: listStatus.Items.Add("User from IP " + _sock.RemoteEndPoint); while (_sock.Connected) { // Create Byte to Receive Data: byte[] _Buffer = new byte[1024]; // Create integer to hold how large the Data Received is: int _DataReceived = _sock.Receive(_Buffer); // Lets Server Know Message is Received: listStatus.Items.Add("Message Received..."); // Convert Buffer to a String: string _Message = Encoding.ASCII.GetString(_Buffer); // Post Message to the Server Window: listStatus.Items.Add(_Message); _sock.Close(); } } }
}
// CLIENT APPLICATION: ----------------------------------------------------
namespace TCP__Client { public partial class Form1 : Form { public Form1() { InitializeComponent(); }
// Defind the TCP Client: TcpClient _Client = new TcpClient(); private void btnConnect_Click(object sender, EventArgs e) { // Connect the TCP Client: _Client.Connect("127.0.0.1", 7777); // Show the Client has Connected: listStatus.Items.Add("Connected to Server 127.0.0.1"); } private void btnSend_Click(object sender, EventArgs e) { while (_Client.Connected) { // Create a Stream: Stream _Stream = _Client.GetStream(); // Create Instance of an Encoder: ASCIIEncoding _Asc = new ASCIIEncoding(); byte[] _Buffer = new byte[1024]; // Create Buffer to Send Message: _Buffer = _Asc.GetBytes(txtMessage.Text); // Show Client is Sending Message: listStatus.Items.Add("Tranmitting Message..."); // Write Message to the Stream: _Stream.Write(_Buffer, 0, _Buffer.Length); // Close Stream _Stream.Close(); _Stream.Dispose(); } } }
}
如果有人能解释如何做到这一点,我会非常感激,这样我就可以得到更多信息。我在使用任务和线程方面有一点经验,我需要做些什么?我只是想抓住这个,所以我可以开始学习它。如果有人有任何您认为有帮助的建议或示例,请分享。
答案 0 :(得分:0)
虽然客户端仍然连接到服务器,但请不要故意关闭服务器应用程序上的套接字。由于您必须保持连接以接收另一条消息,因此请重复接收函数调用。如果没有从客户端发送数据,则Receive()函数调用将自动阻止当前线程等待可用数据。如果再次单击客户端应用程序上的发送消息,则数据将可用于服务器,并将取消阻止服务器应用程序上的阻止部分。
您的服务器应用程序可能阻止了AcceptSocket()和Receive()部分的UI线程。单击StartServer按钮时,由于没有可用的传入连接,您的服务器窗口(UI)可能无法响应,并且您无法在listStatus控件上看到消息。因此,最好将这些Socket代码段放在单独的线程上运行,以免阻塞UI线程。要从单独的线程处理UI组件,需要进行线程安全的UI操作。
以下是我所做的更改:
服务器
namespace Tcp_Server
{
public partial class Form1 : Form
{
delegate void AddTextCallback(string text);
public Form1()
{
InitializeComponent();
}
private void btnStartServer_Click(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(ServerHandler));
}
private void ServerHandler(object args)
{
TcpListener _listner = new TcpListener(IPAddress.Parse("127.0.0.1"), 7777);
// Start The Listner:
_listner.Start();
//Show the server is now listening (Note: UI Thread-Safe is required):
AddText("Server started - Listening on port 7777");
//Create a socket to accept - This is a Blocking Call:
Socket _sock = _listner.AcceptSocket();
//When Client Connects show server has accepted the socket:
AddText("User from IP " + _sock.RemoteEndPoint);
while (_sock.Connected)
{
// Create Byte to Receive Data:
byte[] _Buffer = new byte[1024];
// Create integer to hold how large the Data Received is:
int _DataReceived = _sock.Receive(_Buffer);
if (_DataReceived == 0)
{
// Socket has been shutdown by the client.
break;
}
// Lets Server Know Message is Received:
AddText("Message Received...");
// Convert Buffer to a String:
string _Message = Encoding.ASCII.GetString(_Buffer);
// Post Message to the Server Window:
AddText(_Message);
}
_sock.Close();
//When Client disconnect from the server:
AddText("Client Disconnected.");
_listner.Stop();
AddText("Server Stop.");
}
private void AddText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.listStatus.InvokeRequired)
{
AddTextCallback d = new AddTextCallback(AddText);
this.Invoke(d, new object[] { text });
}
else
{
this.listStatus.Items.Add(text);
}
}
}
}
客户端
namespace Tcp_Client
{
public partial class Form1 : Form
{
// Defind the TCP Client:
TcpClient _Client = null;
Stream _Stream = null;
public Form1()
{
InitializeComponent();
}
private void btnConnect_Click(object sender, EventArgs e)
{
_Client = new TcpClient();
// Connect the TCP Client:
_Client.Connect("127.0.0.1", 7777);
// Show the Client has Connected:
listStatus.Items.Add("Connected to Server 127.0.0.1");
// Create a Stream:
_Stream = _Client.GetStream();
}
private void btnSend_Click(object sender, EventArgs e)
{
if (_Client.Connected)
{
// Create Instance of an Encoder:
ASCIIEncoding _Asc = new ASCIIEncoding();
byte[] _Buffer = new byte[1024];
// Create Buffer to Send Message:
_Buffer = _Asc.GetBytes(txtMessage.Text);
// Show Client is Sending Message:
listStatus.Items.Add("Tranmitting Message...");
// Write Message to the Stream:
_Stream.Write(_Buffer, 0, _Buffer.Length);
}
}
private void btnDisconnect_Click(object sender, EventArgs e)
{
_Stream.Close();
_Stream.Dispose();
_Client.Close();
listStatus.Items.Add("Disconnected from server.");
}
}
}