TCP/IP Continuously receive message without closing the connection - c#

I've been watching the following pair of videos on how to create a TCP/IP connection : Server and Client
What I need to do is create a game (flipcard) in which I send only 2 coordinates for a matrix. Nothing more. Or less.
(the code will follow)
From what I've observed, he closes and reopens the connection, everytime he send a message. It's working. But what do I modify in the code to keep the connection open and detect when a message arrived ?
All my google-searches brought me to these 2 methods:
I have had luck using the socket object directly (rather than the TCP client). (But I do not want to use sockets)
Also uses sockets
When I click to start the server
private void bStartServer_Click(object sender, EventArgs e)
{
Thread tcpServerRunThread = new Thread(new ThreadStart(TCPServerRun));
tcpServerRunThread.Start();
}
Server Runs and waits for a connection
private void TCPServerRun()
{
TcpListener tcpListener = new TcpListener(IPAddress.Any, 2016);
tcpListener.Start();
updateUI("Listening");
while (true)
{
TcpClient client = tcpListener.AcceptTcpClient();
updateUI("Connected");
Thread tcpHandlerThread = new Thread(new ParameterizedThreadStart(tcpHandler));
tcpHandlerThread.Start(client);
}
}
I handle my message
private void tcpHandler(object client)
{
TcpListener tcpListener = new TcpListener(IPAddress.Any, 5004);
TcpClient mClient = (TcpClient)client;
NetworkStream stream = mClient.GetStream();
byte[] message = new byte[1024];
stream.Read(message,0, message.Length);
updateUI("New message = " + Encoding.ASCII.GetString(message));
stream.Close();
mClient.Close();
}
NOTE: updateUI is a function made by him to update a listbox item
Client side - almost like the server side
`private void button1_Click(object sender, EventArgs e)
{
Thread mThread = new Thread(new ThreadStart(ConnectAsClient));
mThread.Start();
}
private void ConnectAsClient()
{
// aici putem inlocui cu adresa de IP dorita
//client.Connect(IPAddress.Parse(textBox.Text), 5004);
client = new TcpClient();
//client.Connect(IPAddress.Parse("127.0.0.1"), 2016); // for when I'm not connected to network
client.Connect(IPAddress.Parse("my_ip_here"), 2016); // for when I am connected to the network
updateUI("connected");
NetworkStream stream = client.GetStream();
string s = "Hello world!";
byte[] message = Encoding.ASCII.GetBytes(s);
stream.Write(message, 0, message.Length);
this.updateUI("Message sent!");
stream.Close();
// client.Close();
}`
If I'm not wrong, everytime he connects again, he creates a new connection, and not open the old one, right?
(It's my first time using TCP/IP, learning on my own, so I'd rather not use sockets, if possible)
-----------------------------------------------------------------------
Full link to my code (slighty modified from the videos provided at the beginning):
TCPClient
TCPServer

You are reconnecting every time you send the message. Use two different methods for this; one for connecting to the server and then another one for actually sending the message. Like so:
TcpClient client;
private void ConnectAsClient()
{
//client.Connect(IPAddress.Parse(textBox.Text), 5004);
client = new TcpClient();
//client.Connect(IPAddress.Parse("127.0.0.1"), 2016);
client.Connect(IPAddress.Parse("my_ip_here"), 2016);
updateUI("connected");
}
void SendMessage()
{
NetworkStream stream = client.GetStream();
string s = "Hello world!";
byte[] message = Encoding.ASCII.GetBytes(s);
stream.Write(message, 0, message.Length);
this.updateUI("Message sent!");
}

Related

TCPListener in windows form

I am trying to write a TCP listener that can connect to multiple clients and send and receive data.
Some of my code -
Calling server -
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'cresijCamDataSet1.CentralControl' table. You can move, or remove it, as needed.
this.centralControlTableAdapter1.Fill(this.cresijCamDataSet1.CentralControl);
s = new Server();
Thread th = new Thread(s.Run);
th.Start();
}
Run Method -
public async void Run()
{
tcp = new TcpListener(IPAddress.Any, 1200);
tcp.Start();
while (true)
{
try
{
TcpClient client = await tcp.AcceptTcpClientAsync();
Thread th = new Thread(()=>{
Process(client);
}) ;
}
catch (Exception ex)
{
string m = ex.Message;
}
}
}
private async Task Process(TcpClient tcpClient)
{
bool hasItem = clients.Contains(tcpClient);
if(hasItem == false)
{
clients.Add(tcpClient);
}
IPEndPoint iPEndPoint =(IPEndPoint) tcpClient.Client.RemoteEndPoint;
string ip = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address.ToString();
NetworkStream stream = tcpClient.GetStream();
byte[] receivedBytes = new byte[tcpClient.ReceiveBufferSize];
stream.Read(receivedBytes, 0, receivedBytes.Length);
f.UpdateData(receivedBytes, ip);
}
Sender Method to send data -
public void Sender(byte[] data, TcpClient client)
{
NetworkStream stream = client.GetStream();
stream.Write(data, 0, data.Length);
}
As you can see I have called Run() method in formLoad. But this all is not working as I dont have much knowledge of threads.
This method is not continuous. The server is not listening to clients always. Can someone help me with this. I need asynchronuous tcp listener that can listen to incoming clients and that too in windows form. Console Server I have.

TcpClient/TcpServer/Listener, Server stops reading or client stops after 30 seconds

Client
class Client
{
public TcpClient client;
public StreamWriter server;
public ServerPlayer serverPlayer;
public Player player;
public void Connect(Player p)
{
player = p;
serverPlayer = new ServerPlayer();
client = new TcpClient(AddressFamily.InterNetwork);
client.Connect("Don't wory my IPV4 Is Here", 8888);
NetworkStream stream = client.GetStream();
server = new StreamWriter(stream);
Timer t = new Timer(Send, null, 0, 10);
}
public void Send(Object o)
{
server.WriteLine("Hello I am bob");
server.Flush();
}
}
Server
class TcpServerConnection
{
private static TcpListener tcpListener;
static void Main(string[] args)
{
tcpListener = new TcpListener(IPAddress.Any, 8888);
tcpListener.Start();
Console.WriteLine("Server started.");
while (true)
{
//blocks until a client has connected to the server
TcpClient client = tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private static void HandleClientComm(object client)
{
while (true)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
StreamReader server = new StreamReader(clientStream);
Console.WriteLine(server.ReadLine());
}
}
}
Problem
Track of events:
Started!
Hello I am bob
Hello I am bob
(Many Hello I am bobs later)
Hello I am bob
(Hello I am bobs just stopped)
(About 30 seconds)
Don't know if it because the client stops sending or server stops receiving or both!? But once this is ran about 30 seconds into this the server stops getting the send information. No error is thrown simply it just doesn't send.
Found out it was my internet. After my google-fu. I set my port for my server to be TCP open. Found out my router was getting suspicious after a spam of messages going into a random port. IP:IPV4 PORT:8888 SETTINGS:OPEN
Ok in your ServerConnection object the first while loop is fine. but the one in your handler is going to cause some problems try this:
private static void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
using(var stream = new StreamReader(clientStream))
{
while (stream.Peek() >= 0)
{
Console.WriteLine(server.ReadLine());
}
}
}
Since you are creating one and only one connection to the Server, and then sending messages constantly in the Client, accordingly when handling the client messages in the Server program, you should accept a TcpClient and then read messages in a loop, instead of accepting a Tcplient and reading a message all in a loop.
private static void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
StreamReader server = new StreamReader(clientStream);
while (true)
{
Console.WriteLine(server.ReadLine());
}
}

How to test TcpListener for localhost and port number in c#

I have a code in c# which reads the data from tcp ipaddress and port number but my problem is this that i dont have any testing plateform with ipaddress and port number to test the application.My concern is this that is there any way by which i can test my code in local environmnet..
Here is my code..
public class Listener
{
private TcpListener tcpListener;
private Thread listenThread;
// Set the TcpListener on port 8081.
Int32 port = 8081;
IPAddress localAddr = IPAddress.Parse("192.168.1.3");
Byte[] bytes = new Byte[256];
public void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
public void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
//a socket error has occured
// System.Windows.MessageBox.Show("socket");
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
// System.Windows.MessageBox.Show("disc");
break;
}
//message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
String textdata = encoder.GetString(message, 0, bytesRead);
System.IO.File.AppendAllText(#"D:\ipdata.txt", textdata);
}
tcpClient.Close();
}
}
Please help me to solve this ..
Thanks in advance..
To test the TCP listening application, you obviously need to write TCP transferring one. You can write it and:
Run them simultaneously
OR
Run listener on your OS and transmitter in virtual machine. I made so and has written a post on my blog on Russian (sources are also available for download).
I think you can configure the listener to 127.0.0.1 and test logic via localhost connetcion if you have transmitting part of system
Use RESTClient chrome/firefox AddOn (http://restclient.net/) to send data to IP and Port in Intranet environment, I use this

C# TCP Client having trouble listening to Server and updating GUI

I have a GUI with 2 buttons and a text box. Button1 starts a server and has it listen for clients. Button 2 sends a connection request to the server and starts to listen for anything the server will send to the client (responses). Although w/ my current code when the Server sends the reply and I try to write it to a text box the whole system hangs.
Code as seen below:
Server Class:
class Server
{
private TcpListener tcpListener;
private Thread listenThread;
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
//a socket error has occured
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}
//message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Client!");
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
tcpClient.Close();
}
public Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 3000);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
}
GUI class:
private void buttonServerStart_Click(object sender, EventArgs e)
{
Server Myserver = new Server();
}
//Greet the Server and listen for response...
private void EthStartB_Click(object sender, EventArgs e)
{
TcpClient client = new TcpClient();
byte[] message = new byte[4096];
int bytesRead;
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);
client.Connect(serverEndPoint);
NetworkStream clientStream = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Server!");
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
//start listening
this.ClientListener.Start();
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
//a socket error has occured
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}
//message has successfully been received
tb_recieved.Clear();
tb_recieved.Text=encoder.GetString(message,0,bytesRead);
}
}
TcpListener ClientListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 3000);
private void EthEndB_Click(object sender, EventArgs e)
{
Form3 frmT = new Form3();
frmT.Show();
}
}
The issue is when private void EthStartB_Click(object sender, EventArgs e) calls the code line of tb_recieved.Text=encoder.GetString(message,0,bytesRead);
The program hangs because you have a while(true) loop in EthStartB_Click which runs on UI thread. clientStream.Read call will block UI thread.
Move the receive logic on a new thread and set the textbox content using Control.Invoke or Dipatcher.Invoke depending on whether you are on WinForms or WPF - and do that only if you do have some content in the message to be written to textbox.
There also another issue, since you have the tcpClient.Close() outside the while loop on the server, neither client nor server will disconnect. Both will block on their respective stream.Read calls.
Since you are running both client and server on same machine, that TcpListener ClientListener is not required and will not play well with the server already listening on the same port.

Windows Service closed when I disconnect one client socket

I have a server listened on a socket. This server is a Windows Service.
My problem is: When I disconnect a client socket.Disconnect(false); the service so closed and other clients are closed forcibly or new connections refused. I think that when service kill this client thread, the service not back to main thread.
Paste my code used for service (server functionality). Is correct the management of threads?
I run server with
this.tcpListener = new TcpListener(ipEnd);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
//a socket error has occured
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}
//message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
System.Diagnostics.Debug.WriteLine(encoder.GetString(message, 0, bytesRead));
}
tcpClient.Close();
}
Sorry for my bad english and thanks for any suggestion
The code you provided seems to be almost correct.
The only reason your app will crash is the line
NetworkStream clientStream = tcpClient.GetStream();
If you look at the documentation for GetStream(), you could see that it can throw InvalidOperationException if client is not connected. So in the situation when client connects and immediately disconnects it could be an issue.
So just guard this code with try-catch.
Also sometimes you might not get an explicit exception report, but have crash in multithreaded applications. To handle such exceptions subscribe to the AppDomain.CurrentDomain.UnhandledException event.

Categories