36308

Receive multiple different messages TcpListener C#

Question:

Hey guys I have been trying to learn how to send some simple text messages between client server using TcpListener and sockets. I have read many threads that appear to be showing how to read the _Buffer in lets say a loop to ensure the whole message is read. However, I can't seem to figure out how to get the second message after the first one is received. I can connect to the server just fine and I can get the first message just fine. However, if I hit the send button on my Client again no message gets to the server. Here is my code:

// 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(); } } }

}

I would greatly appreciate if someone could explain how to make this so I can get more then one message. I do have a little experience in using Tasks and threading, is that something I need to do? I'm just trying to get a grasp on this so I can start learning it. If anyone has any recommendations or examples that you think could help please do share.

Answer1:

While the client is still connected to the server, don't close the socket on the server app deliberately. As you must keep alive the connection to receive another message, repeat the receive function call. If there is no data sent from the client, the Receive() function call will automatically block your current thread to wait for available data. If you click send message on the client application again, the data will be available for the server and will unblock that blocking part on the server app.

Your server application might be blocking the UI thread on the AcceptSocket() and Receive() part. When the StartServer button is clicked, your server window (UI) might become not responding because of no incoming connection available and you cannot see messages on your listStatus control. Thus, it is better to put those pieces of Socket code to run on a seperate thread in order not to block the UI thread. To work on the UI component from the seperate thread, a thread-safe UI manipulation is required to do so.

Here is the changes I have made:

Server

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); } } } }

Client

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."); } } }

Recommend

  • Python asyncore UDP server
  • Main Python Process is stopped using subprocess calls in SocketServer
  • Getting answer from Jabber Server
  • Got Error when Implementing C# Tcp Hole Punching - Cannot Connect Behind NAT
  • How to check TCP/IP port availability using C# (Socket Communication)
  • Python socket.error: [Errno 111] Connection refused on ubuntu 12.04
  • How do I create a pie chart in Java
  • Interaction with python's matplotlib figure: assign value to selected features
  • How to send an std::vector of unsigned char over an UDP socket using boost asio?
  • Connection between Node.JS and PHP via UNIX Socket - EPIPE write error
  • Get pretty git rev name
  • How to read data from socket connection - android
  • Is it expensive to create the Thread object or to actually start the thread?
  • Cannot send user message with Spring Websocket
  • SSLRead() return error -9806/15958)
  • JOOQ nested condition
  • Multiple sockets for clients to connect to
  • Google OAuth2 for an web application hosted behind NAT (intranet server without public IP)
  • How to unwind to the first view controller on a navigation stack
  • Getting zero results in search using elastic4s
  • Confirm box return value from alertify plugin and jquery
  • How to resolve docker host names (/etc/hosts) in containers
  • Run script file on remote server
  • Should I be afraid to use UDP to make a client/server broadcast talk?
  • Asynchronous Sockets - Handling false socket.AcceptAsync values
  • Haskell: function composition with anonymous/lambda function
  • Receiver has no segue with identifier“***”
  • If I am creating a simple client server application in IntelliJ, how should this work?
  • Error in making a socket connection
  • New Firebase failed: First argument must be a valid firebase URL and the path can't contain “.”
  • java inputstream
  • Cannot resolve symbol 'MyApi'
  • Avoid links criss cross / overlap in d3.js using force layout
  • Recording logins for password protected directories
  • ExecuteAsync RestSharp to allow backgroundWorker CancellationPending c#
  • How do I configure my settings file to work with unit tests?
  • Change div Background jquery
  • How does Linux kernel interrupt the application?
  • Busy indicator not showing up in wpf window [duplicate]
  • Why do underscore prefixed variables exist?