C# multi tcp server - c#

So i got this multi thread tcp server code, it is working great, but i can not switch between clients.
So my question is how can i switch between clients?
I am planing to switch the server to winforms but i do not know how to access other threads.
Also, please tell what should i improve and better ways of sanitizing user input.
Here is the server code:
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace Server
{
class Program
{
const int PORT_NO = 5000;
const string SERVER_IP = "127.0.0.1";
static void Main(string[] args)
{
//---listen at the specified IP and port no.---
IPAddress localAdd = IPAddress.Parse(SERVER_IP);
TcpListener listener = new TcpListener(localAdd, PORT_NO);
//---prepare client counter---
int num = 0;
//---announce and start listening---
Console.WriteLine("Listening...");
listener.Start();
while (true)
{
//---incoming client connected---
TcpClient client = listener.AcceptTcpClient();
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
//---add 1 to total clients---
num = num + 1;
//---check if current thread name is null, if yes set the current client position---
if (Thread.CurrentThread.Name == null)
{
Thread.CurrentThread.Name = num.ToString();
}
else
{
Console.WriteLine("Unable to name a previously " +
"named thread.");
}
string clientip = ((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString();
//---write that client connected and write its ip---
Console.WriteLine("Client connected: [IP: {0}, Client: {1}]", clientip, Thread.CurrentThread.Name);
//---loop for infinite amount of time---
while (true)
{
try
{
//---Make thread background---
Thread.CurrentThread.IsBackground = true;
//---get the incoming data through a network stream---
NetworkStream nwStream = client.GetStream();
new Thread(() =>
{
byte[] buffer = new byte[client.ReceiveBufferSize];
//---read incoming stream---
int bytesRead = nwStream.Read(buffer, 0, client.ReceiveBufferSize);
//---convert the data received into a string---
string dataReceived = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine("[IP: {0}, Client: {1}]: " + dataReceived, clientip, Thread.CurrentThread.Name);
}).Start();
//---write back the text to the client---
Console.WriteLine("Enter data to send back to [IP: {0}, Client: {1}]: ", clientip, Thread.CurrentThread.Name);
//---read user input---
string input = Console.ReadLine();
//---sanitize user input---
if (input == String.Empty)
{
input = #" ";
}
if (input == #"")
{
input = #" ";
}
if (input == null)
{
input = #" ";
}
//---convert ASCII text to bytes---
byte[] send = Encoding.ASCII.GetBytes(input);
//---write bytes to network stream---
nwStream.Write(send, 0, send.Length);
}
catch (Exception)
{
//---close client---
client.Close();
//---Announce disconnect---
Console.WriteLine("Client disconnected [IP: {0}, Client: {1}]", clientip, Thread.CurrentThread.Name);
//---remove 1 from total clients---
num = num - 1;
//---Abort current thread---
Thread.CurrentThread.Abort();
return;
}
}
}).Start();
}
}
}
}
This is the code for client:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace Client
{
class Program
{
const int PORT_NO = 5000;
const string SERVER_IP = "127.0.0.1";
static void Main(string[] args)
{
//---data to send to the server---
string textToSend = "Received the text.";
//---create a TCPClient object at the IP and port no.---
TcpClient client = new TcpClient(SERVER_IP, PORT_NO);
while (true)
{
NetworkStream nwStream = client.GetStream();
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(textToSend);
//---send the text---
Console.WriteLine("Sending : " + textToSend);
nwStream.Write(bytesToSend, 0, bytesToSend.Length);
//---read back the text---
byte[] bytesToRead = new byte[client.ReceiveBufferSize];
int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize);
Console.WriteLine("Received : " + Encoding.ASCII.GetString(bytesToRead, 0, bytesRead));
}
client.Close();
}
}
}

Related

check when a client is disconnected

I have a console application in c#
this code can tell me when a client si connected in TCP to port 3001 and the message sent
I cant understand when he disconnects, its going into while (client.Connected) unlimited, i tried to check with a PING but sometimes returns false even if connnected,
I am stuck
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
int port = 3001;
TcpListener listener = new TcpListener(IPAddress.Any, port);
listener.Start();
Console.WriteLine("Listening on port " + port + "...");
while (true)
{
TcpClient client = listener.AcceptTcpClient();
Console.WriteLine("Accepted connection from " + client.Client.RemoteEndPoint.ToString());
while (client.Connected)
{
NetworkStream stream = client.GetStream();
if (stream.DataAvailable)
{
byte[] buffer = new byte[1024];
int bytesRead = stream.Read(buffer, 0, buffer.Length);
string data = Encoding.UTF8.GetString(buffer, 0, bytesRead);
Console.WriteLine("Received data: " + data);
}
//check if client still connected
string[] cli = client.Client.RemoteEndPoint.ToString().Split(Convert.ToChar(":"));
string Host = cli[0];
int Uri = port;// int.Parse(cli[1]);
if (PingHost(Host,Uri)==false)
{
Console.WriteLine("Client disconnected.");
break;
}
}
}
}
public static bool PingHost(string hostUri, int portNumber)
{
try
{
using (var client = new TcpClient(hostUri, portNumber))
return true;
}
catch (SocketException ex)
{
//MessageBox.Show("Error pinging host:'" + hostUri + ":" + portNumber.ToString() + "'");
return false;
}
}
}
}

TCP Service & REST APIs

I have a GPS Tracker Device, I have run a TCP/IP Server Code which Successfully establishes connection with each device in a separate Thread and Device Keep sending its heart beat after one minute and server replies ON. When I send a command to get device location it gives me location and everything is working fine.
Now I want to get location from an android device using web service, Now I'm confuse how can I use running thread of a specific device from an Android App?
class Server
{
TcpListener server = null;
public Server(string ip, int port)
{
IPAddress localAddr = IPAddress.Parse(ip);
server = new TcpListener(localAddr, port);
server.Start();
StartListener();
}
public void StartListener()
{
try
{
while (true)
{
Console.WriteLine("Waiting for a connection... ");
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
Thread t = new Thread(new ParameterizedThreadStart(HandleDeivce));
t.Start(client);
}
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
}
public void HandleDeivce(Object obj)
{
TcpClient client = (TcpClient)obj;
NetworkStream stream = client.GetStream();
string data = null;
Byte[] bytes = new Byte[256];
int i;
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
data = Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("{1}: Received: {0}", data, Thread.CurrentThread.ManagedThreadId);
if (data.StartsWith("##"))
{
data = "LOAD";
}
else
{
data = "ON";
}
byte[] msg = Encoding.ASCII.GetBytes(data);
stream.Write(msg, 0, msg.Length);
Console.WriteLine("{1}: Sent: {0}", data, Thread.CurrentThread.ManagedThreadId);
}
client.Close();
}
}
Try making code look like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace ConsoleApplication16
{
class Program
{
const string IP = "123.456.789.000";
const int PORT_NUMBER = 1234;
static AutoResetEvent autoEvent = new AutoResetEvent(false);
static void Main(string[] args)
{
GPSClient client = new GPSClient(IP, PORT_NUMBER);
//start http client or equivalent here
while (true)
{
autoEvent.Reset();
autoEvent.WaitOne();
//wait for message from user/client on service port
string message = client.message;
//send message back to user/client
}
}
}
public class WebServer
{
}
public class GPSClient
{
const int BUFFER_SIZE = 256;
TcpClient client = null;
NetworkStream stream = null;
Byte[] bytes = new Byte[BUFFER_SIZE];
public string message { get; set; }
public GPSClient(string ip, int port)
{
try
{
Console.WriteLine("Connecting to Device... ");
client.Connect(ip, port);
Console.WriteLine("Connected!");
stream = client.GetStream();
stream.BeginRead(bytes, 0, BUFFER_SIZE, new AsyncCallback(HandleDeivce), stream);
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
}
public void HandleDeivce(IAsyncResult ar)
{
NetworkStream stream = ar.AsyncState as NetworkStream;
string data = null;
int i = stream.Read(bytes, 0, BUFFER_SIZE);
data = Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);
message = data;
if (data.StartsWith("##"))
{
data = "LOAD";
}
else
{
data = "ON";
}
byte[] msg = Encoding.ASCII.GetBytes(data);
stream.Write(msg, 0, msg.Length);
Console.WriteLine("Sent: {0}", data);
stream.BeginRead(bytes, 0, BUFFER_SIZE, new AsyncCallback(HandleDeivce), stream);
}
}
}

Simple TCP chat application c#

I try to make the LAN chat application, use Send() and Receive() function in C# to send and receive message. But the problem is that, when user type in message into Console and press Enter keyboard, this content suddenly appear in Console Screen before WriteLine my form appear (For example: what I expected is You: hello)
How could I remove line "hello". What I expecting is:
Client: hi
You: hello
Code for Server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace SimpleTcpSrvr
{
class Program
{
static void Main(string[] args)
{
Console.OutputEncoding = Encoding.UTF8;
int recv;
byte[] data = new byte[1024];
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"),9050);
Socket newsock = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
newsock.Bind(ipep);
newsock.Listen(10);
Console.WriteLine("Waiting for a client...");
Socket client = newsock.Accept();
IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("Connected with {0} at port {1}",clientep.Address,clientep.Port);
string welcome = "Welcome to my test server";
data = Encoding.UTF8.GetBytes(welcome);
client.Send(data,data.Length,SocketFlags.None);
string input;
while (true)
{
data = new byte[1024];
recv = client.Receive(data);
if (recv == 0)
break;
Console.WriteLine("Client: "+Encoding.UTF8.GetString(data, 0, recv));
input = Console.ReadLine();
Console.WriteLine("You: " + input);
client.Send(Encoding.UTF8.GetBytes(input));
}
Console.WriteLine("Disconnected from {0}", clientep.Address);
client.Close();
newsock.Close();
Console.ReadLine();
}
}
}
Code for Client:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace SimpleTcpClient
{
class Program
{
static void Main(string[] args)
{
Console.OutputEncoding = Encoding.UTF8;
byte[] data = new byte[1024];
string input, stringData;
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"),9050);
Socket server = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
try
{
server.Connect(ipep);
}
catch(SocketException e)
{
Console.WriteLine("Unable to connect to server.");
Console.WriteLine(e.ToString());
return;
}
int recv = server.Receive(data);
stringData = Encoding.UTF8.GetString(data, 0, recv);
Console.WriteLine(stringData);
while (true)
{
input = Console.ReadLine();
if (input == "exit")
break;
Console.WriteLine("You: " + input);
server.Send(Encoding.UTF8.GetBytes(input));
data = new byte[1024];
recv = server.Receive(data);
stringData = Encoding.UTF8.GetString(data, 0, recv);
byte[] utf8string = System.Text.Encoding.UTF8.GetBytes(stringData);
Console.WriteLine("Server: "+stringData);
}
Console.WriteLine("Disconnecting from server...");
server.Shutdown(SocketShutdown.Both);
server.Close();
Console.WriteLine("Disconnected!");
Console.ReadLine();
}
}
}
Thanks everyone!
You could try this, Set the cursor position back to the start of the previous line after ReadLine & then overwrite the line with your text - in your case as you are prepending "You: " your output string will be longer than the input string - if it were smaller you could overwrite with spaces to clear any excess characters.
input = Console.ReadLine();
Console.SetCursorPosition(0, Console.CursorTop-1);
Console.WriteLine("You: " + input);

Client send message server not received message in tcp/ip socket program

TCP/IP socket program client send text server receive and store database table. I'm righting code below but i have error text reeving time.
This is Client Side Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.IO;
namespace ClientApplication
{
class Client
{
static void Main(string[] args)
{
try
{
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Connecting.....");
//tcpclnt.Connect("162.144.85.232", 8080);
tcpclnt.Connect("162.144.85.232", 4489);
Console.WriteLine("Connected");
Console.Write("Enter the string to be Sent : ");
String str = Console.ReadLine();
Stream stm = tcpclnt.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(str);
System.Net.ServicePointManager.Expect100Continue = false;
Console.WriteLine("Sending.....");
stm.Write(ba, 0, ba.Length);
byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
for (int i = 0; i < k; i++)
Console.Write(Convert.ToChar(bb[i]));
Console.ReadLine();
tcpclnt.Close();
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
Console.ReadLine();
}
}
}
}
This Is Server Side Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace ServerApplication
{
class Server
{
static void Main(string[] args)
{
try
{
IPAddress ipadd = IPAddress.Parse("192.168.1.7");
TcpListener list = new TcpListener(ipadd, 8080);
list.Start();
Console.WriteLine("The server is running at port 8080...");
Console.WriteLine("The Local End point Is:" + list.LocalEndpoint);
System.Net.ServicePointManager.Expect100Continue = false;
Socket s = list.AcceptSocket();
Console.WriteLine("Connections Accepted from:" + s.RemoteEndPoint);
byte[] b = new byte[100];
int k = s.Receive(b);
Console.WriteLine("Recived...");
for (int i = 0; i < k; i++)
Console.WriteLine(Convert.ToChar(b[i]));
ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes("The String Was Recived throw Server"));
Console.WriteLine("\n Sent Acknowlegment");
s.Close();
list.Stop();
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
}
}
}
}
I'm trying to execute this code i have error happen like this
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. Please resolve my issue .
There are a number of problems with the code you posted, but the one directly causing the behavior you're seeing is that the server closes the socket without waiting for the client to finish reading from the connection.
Look up "TCP graceful shutdown" for more information. In the meantime, the following is an improvement on the code you posted and won't have that problem:
Server code:
class Server
{
static void Main(string[] args)
{
try
{
TcpListener list = new TcpListener(IPAddress.Any, 8080);
list.Start();
Console.WriteLine("The server is running at port 8080...");
Console.WriteLine("The Local End point Is:" + list.LocalEndpoint);
Socket s = list.AcceptSocket();
Console.WriteLine("Connections Accepted from:" + s.RemoteEndPoint);
byte[] b = new byte[100];
int k;
while ((k = s.Receive(b)) > 0)
{
Console.WriteLine("Recived...");
Console.WriteLine(Encoding.ASCII.GetString(b, 0, k));
s.Send(Encoding.ASCII.GetBytes("The String Was Recived throw Server"));
Console.WriteLine("\n Sent Acknowlegment");
}
s.Shutdown(SocketShutdown.Both);
s.Close();
list.Stop();
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
}
}
}
Client code:
class Client
{
static void Main(string[] args)
{
try
{
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Connecting.....");
tcpclnt.Connect("192.168.1.7", 8080);
Console.WriteLine("Connected");
Console.Write("Enter the string to be Sent : ");
String str = Console.ReadLine();
Stream stm = tcpclnt.GetStream();
byte[] ba = Encoding.ASCII.GetBytes(str);
Console.WriteLine("Sending.....");
stm.Write(ba, 0, ba.Length);
tcpclnt.Client.Shutdown(SocketShutdown.Send);
byte[] bb = new byte[100];
int k;
while ((k = stm.Read(bb, 0, 100)) > 0)
{
Console.WriteLine(Encoding.ASCII.GetString(bb, 0, k));
}
Console.ReadLine();
tcpclnt.Close();
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
Console.ReadLine();
}
}
}
The key thing here is that both server and client continue to read from the connection until the remote end has, by calling Socket.Shutdown(), signaled that there is no more data to be read.
I also removed the use of the System.Net.ServicePointManager.Expect100Continue property, which had no effect in this code. That only affects programs that use the ServicePoint class and is not useful here.
It's also not clear to me why for the client you use the NetworkStream instead of just getting the Client socket and using it directly. The NetworkStream object is useful when wrapping your I/O in e.g. StreamReader and StreamWriter, but here you're just using Stream.Read() and Stream.Write(), which have the exact same semantics as Socket.Receive() and Socket.Send(), respectively. In any case, note that while you are using the NetworkStream object for the send and receive, you still need to access the underlying Socket instance directly to correctly initiate the graceful shutdown (the endpoint not initiating could just close the NetworkStream, since it doesn't have to shutdown until it's done both sending and receiving).
I also cleaned up the handling of the ASCII-encoded text a bit.

how to send and receive string continously using sockets in c#

Basically what i am stuck at is , i want my client to send data continously and server to read from client as it sends, like when i send "2" it should read "2" and display and so on it should continue to read as long as i send from the client, i can stop or exit whenever i press some different character,.
what i have acheived is not continous, i send from client 2 and server receives 2 and then it is stopped, i want to send them continously , i am pasting below my code,
client.cs
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace Client
{
class Program
{
const int port = 8001;
const string ip = "127.0.0.1";
const int maxBuffer = 100;
static void Main(string[] args)
{
try
{
while (true)
{
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Connecting.....");
tcpclnt.Connect("127.0.0.1", 8001);
// use the ipaddress as in the server program
Console.WriteLine("Connected");
Console.Write("Enter the string to be transmitted : ");
String str = Console.ReadLine();
Stream stm = tcpclnt.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(str);
Console.WriteLine("Transmitting.....");
stm.Write(ba, 0, ba.Length);
byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
for (int i = 0; i < k; i++)
Console.Write(Convert.ToChar(bb[i]));
Console.ReadLine();
tcpclnt.Close();
}
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
}
}
}
}
server.cs
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace Server
{
class Program
{
const int port = 8001;
const string ip = "127.0.0.1";
const int maxBuffer = 100;
static void Main(string[] args)
{
try
{
IPAddress ipAd = IPAddress.Parse("127.0.0.1");
// use local m/c IP address, and
// use the same in the client
while (true)
{
/* Initializes the Listener */
TcpListener myList = new TcpListener(ipAd, 8001);
/* Start Listeneting at the specified port */
myList.Start();
Console.WriteLine("The server is running at port 8001...");
Console.WriteLine("The local End point is :" +
myList.LocalEndpoint);
Console.WriteLine("Waiting for a connection.....");
Socket s = myList.AcceptSocket();
Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);
byte[] b = new byte[100];
int k = s.Receive(b);
Console.WriteLine("Recieved...");
for (int i = 0; i < k; i++)
Console.Write(Convert.ToChar(b[i]));
ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes("The string was recieved by the server."));
Console.WriteLine("\nSent Acknowledgement");
Console.ReadLine();
/* clean up */
s.Close();
myList.Stop();
}
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
}
}
}
}
Any help will be appreciated
Thanks :)
By using MultiThread you can send and receive message between client and server continuously.
Server side example:
IPAddress[] ipAdd = Dns.GetHostAddresses("192.168.1.38");
IPAddress ipAddress = ipAdd[0];
TcpListener serverSocket = new TcpListener(ipAddress, 8888);
TcpClient clientSocket = default(TcpClient);
int counter = 0;
serverSocket.Start();
notifyIcon.ShowBalloonTip(5000, "Server Notification", " >> Server Started.", wform.ToolTipIcon.Info);
counter = 0;
while (true)
{
counter += 1;
clientSocket = serverSocket.AcceptTcpClient();
byte[] bytesFrom = new byte[10025];
string dataFromClient = null;
NetworkStream networkStream = clientSocket.GetStream();
networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
dataFromClient = Encoding.ASCII.GetString(bytesFrom);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
if (clientsList.ContainsKey(dataFromClient))
{
continue;
}
else
{
clientsList.Add(dataFromClient, clientSocket);
}
string onlineUsers = "";
foreach (DictionaryEntry item in clientsList)
{
onlineUsers += item.Key.ToString() + ";";
}
onlineUsers = onlineUsers.Remove(onlineUsers.Length - 1);
Broadcast.BroadcastSend(dataFromClient + " joined. |" + onlineUsers, dataFromClient, ref clientsList, false, false);
notifyIcon.ShowBalloonTip(5000,"Client Notification", dataFromClient + " joined.", wform.ToolTipIcon.Info);
HandleClient client = new HandleClient();
client.StartClient(clientSocket, dataFromClient, clientsList, notifyIcon);
}
More details
Ignore my earlier answer
The problem is that the server is waiting for user response in console after sending acknowledgement.
Console.ReadLine();
Just comment out this line in your original program.
And add a exit condition by checking the input.
Also as the previous poster suggest, make it thread based if you want multiple clients connecting to this server simultaneously.

Categories