Multithreaded TCP server and client - c#

I just search around before asking this problem, looking for example of TCP Server and Client in C#.
I found this link, I just used the given code by the link but unfortunately there's a problem and I'm stuck!
The following code is the complete code for server (console):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
namespace TCP_Server_Console
{
class Program
{
static void Main(string[] args)
{
TcpListener serverSocket = new TcpListener(8888);
int requestCount = 0;
TcpClient clientSocket = default(TcpClient);
serverSocket.Start();
Console.WriteLine(" >> Server Started");
clientSocket = serverSocket.AcceptTcpClient();
Console.WriteLine(" >> Accept connection from client");
requestCount = 0;
while ((true))
{
try
{
requestCount = requestCount + 1;
NetworkStream networkStream = clientSocket.GetStream();
byte[] bytesFrom = new byte[10025];
networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
Console.WriteLine(" >> Data from client - " + dataFromClient);
string serverResponse = "Last Message from client" + dataFromClient;
Byte[] sendBytes = Encoding.ASCII.GetBytes(serverResponse);
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
Console.WriteLine(" >> " + serverResponse);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
clientSocket.Close();
serverSocket.Stop();
Console.WriteLine(" >> exit");
Console.ReadLine();
}
}
}
/*HandleClient Class */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace TCP_Server_Console
{
public class HandleClient
{
TcpClient clientSocket;
string clNo;
public void startClient(TcpClient inClientSocket, string clineNo)
{
this.clientSocket = inClientSocket;
this.clNo = clineNo;
Thread ctThread = new Thread(doChat);
ctThread.Start();
}
private void doChat()
{
int requestCount = 0;
byte[] bytesFrom = new byte[10025];
string dataFromClient = null;
Byte[] sendBytes = null;
string serverResponse = null;
string rCount = null;
requestCount = 0;
while ((true))
{
try
{
requestCount = requestCount + 1;
NetworkStream networkStream = clientSocket.GetStream();
networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
Console.WriteLine(" >> " + "From client-" + clNo + dataFromClient);
rCount = Convert.ToString(requestCount);
serverResponse = "Server to clinet(" + clNo + ") " + rCount;
sendBytes = Encoding.ASCII.GetBytes(serverResponse);
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
Console.WriteLine(" >> " + serverResponse);
}
catch (Exception ex)
{
Console.WriteLine(" >> " + ex.ToString());
}
}
}
}
}
The following code is the complete code for client (Windows Forms):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TCP_Client_Sample
{
public partial class Form1 : Form
{
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
NetworkStream serverStream;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
label_status.Text = "Client Started, Connecting...";
try
{
clientSocket.Connect("127.0.0.1", 8888);
if (clientSocket.Connected)
{
label_status.Text = "Connected";
label_status.ForeColor = Color.Green;
}
}
catch (Exception xe)
{
MessageBox.Show("OOPS!!! SERVER MUST BE STARTED FIRST! \n\n" + xe.ToString());
}
}
//Function to Send Message to Server (On Button Click)
private void btn_send_Click(object sender, EventArgs e)
{
try
{
NetworkStream serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes("Message From Client$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
byte[] inStream = new byte[10025];
serverStream.Read(inStream, 0, (int)clientSocket.ReceiveBufferSize);
string returnData = System.Text.Encoding.ASCII.GetString(inStream);
chatBox.AppendText(">> Server: " + returnData);
}
catch (Exception ex)
{
MessageBox.Show("Unable to Send Data: " + ex);
}
}
}
}
Every time I execute the code of server it works and started. But when I execute the client, the server throws an error
Specified Argument was out of the range
Here is the complete error:
System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: size
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at TCP_Server_Console.Program.Main(String[] args) in C:\Users\user\Documents\Visual Studio 2015\Projects\TCP_Server_Console\TCP_Server_Console\Program.cs:line 50
I'm also getting the same error every time I click the btn_send from client form.
I am stuck here and I don't know what's the problem since this is the first time I'm work with TCP Socket.
Can anynone help me?

The problem lies in that your code used two different sizes
byte[] inStream = new byte[10025];
serverStream.Read(inStream, 0, (int)clientSocket.ReceiveBufferSize);
In this. Youve reserved space for 10025 bytes, but RecieveBufferSize maybe another size, bigger or smaller, but if bigger, it will error.
If you make the read call call the same length as your byte array you wont have your problem.

byte[] inStream = new byte[10025];
byte[] tStream = new byte[(int)clientSocket.ReceiveBufferSize];
serverStream.Read(tStream, 0, (int)clientSocket.ReceiveBufferSize);
Would be the quick easy fix to ensure that the byte buffer its reading into will always be the correct size needed.

Related

C# Error with Online Chat Room

So I am making an online chat room in C#, and I am getting this error on line 71.
System.ArgumentOutOfRangeException: 'Specified argument was out of the range of valid values.'
I have both a client program and a server program. Here is the code to the client program. The line that is giving me the error is in asterisks.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Threading;
namespace ChatProgram
{
public partial class Form1 : Form
{
System.Net.Sockets.TcpClient clientSocket = new
System.Net.Sockets.TcpClient();
NetworkStream serverStream = default(NetworkStream);
string readData = null;
static int maxUsage = 0;
string noName = "Anonymous";
int tick = 0;
public Form1()
{
InitializeComponent();
}
private void enterButton_Click(object sender, EventArgs e)
{
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(readRichTxt.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
readData = "Connected to server...";
msg();
clientSocket.Connect("127.0.0.1", 8888);
serverStream = clientSocket.GetStream();
Thread ctThread = new Thread(getMessage);
ctThread.Start();
string nameTxt = nameTextBox.Text;
if (nameTxt == String.Empty)
{
nameTxt = noName;
tick = 1;
}
else
{
tick = 0;
}
readRichTxt.SelectionColor = Color.Red;
readRichTxt.AppendText("\n" + nameTxt + " has joined." + "\n");
++maxUsage;
sendButton.Enabled = true;
if (maxUsage == 3)
{
enterButton.Enabled = false;
}
}
private void getMessage()
{
while(true)
{
serverStream = clientSocket.GetStream();
int buffSize = 0;
byte[] inStream = new byte[10025];
buffSize = clientSocket.ReceiveBufferSize;
***serverStream.Read(inStream, 0, buffSize);***
string returndata = System.Text.Encoding.ASCII.GetString(inStream);
readData = "" + returndata;
msg();
}
}
private void msg()
{
if (this.InvokeRequired)
this.Invoke(new MethodInvoker(msg));
else
readRichTxt.Text = readRichTxt.Text + Environment.NewLine + " >> " + readData;
}
private void sendButton_Click(object sender, EventArgs e)
{
string nameTxt = nameTextBox.Text;
string userTyped = userTypeBox.Text;
if (userTyped == String.Empty)
{
return;
}
if (tick == 1)
{
readRichTxt.AppendText(noName + ": " + userTyped);
}
else
{
readRichTxt.AppendText(nameTxt + ": " + userTyped);
}
userTypeBox.Clear();
}
}
}
Please help, I am completely stumped at this point.
what is the size of:
buffSize = clientSocket.ReceiveBufferSize;
?
this is likely larger than what you declared here:
byte[] inStream = new byte[10025];
and thus the error is roughly telling you:
buffSize > inStream.Length
which results in the out of bounds like error.

Sockets: Only one usage of each socket address is normally permitted

I want to reuse a socket after I used it once, but I always get subj exception.
I found multiple questions with same issue but no working solution. I tried using code, i tried manual closing - but without any success
A little sample
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace SocketTest
{
class Program
{
static void Main()
{
for (int i = 1; i <= 2; i++)
{
var encoding = new UTF8Encoding(false);
var host = Dns.GetHostEntry("localhost");
var endpoint = new IPEndPoint(host.AddressList[0], 11322);
Console.WriteLine("Iteration #{0}\tEnpdoint = {1}", i, endpoint);
try
{
var client = new TcpClient(endpoint);
const string message = "Hello world!";
byte[] data = encoding.GetBytes(message);
client.Connect(endpoint);
var stream = client.GetStream();
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent: {0}", message);
byte[] receiveData = new byte[4096];
int totalBytes = 0;
while (true)
{
int bytesRead = stream.Read(receiveData, 0, receiveData.Length);
totalBytes += bytesRead;
if (bytesRead < receiveData.Length)
break;
Array.Resize(ref receiveData, 2 * receiveData.Length);
}
var response = encoding.GetString(receiveData, 0, totalBytes);
Console.WriteLine("Received: {0}", response);
client.Client.Shutdown(SocketShutdown.Both);
client.Client.Disconnect(true);
stream.Close();
client.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.WriteLine();
}
}
}
}

system.argumentoufofrange exception :lenght cannot be less than 0 (line 32) overflow exception( Line 29)

Sup people im creating a program to listen to incoming string it works...well that which i have coded so far works the problem is if they send their string my program throws the argument out of range exception
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
namespace Stringlistener
{
class Program
{
static void Main(string[] args)
{
TcpListener serverSocket = new TcpListener(my port number);
int requestCount = 0;
TcpClient clientSocket = default(TcpClient);
serverSocket.Start();
Console.WriteLine(" >> Server Started");
clientSocket = serverSocket.AcceptTcpClient();
Console.WriteLine(" >> Accept connection from client");
requestCount = 0;
while ((true))
{
try
{
requestCount = requestCount + 1;
NetworkStream networkStream = clientSocket.GetStream();
byte[] bytesFrom = new byte[10000000000025];
networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
Console.WriteLine(" >> Data from client - " + dataFromClient);
string serverResponse = "Last Message from client" + dataFromClient;
Byte[] sendBytes = Encoding.ASCII.GetBytes(serverResponse);
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
Console.WriteLine(" >> " + serverResponse);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
clientSocket.Close();
serverSocket.Stop();
Console.WriteLine(" >> exit");
Console.ReadLine();
}
}
}
}
String:
<?xml version="1.0" encoding="utf-8"?>
<faf>
<hah>
<gr>00.00</gr>
<yy>000000000</yy>
</hah>
<ee>
<gr>00.00</gr>
<yy>000000000</yy>
</ee>
</faf>
any ideas? is the problem from my side if so how do i fix it?
A good explanation and answer will be much appreciated i wish to understand this to stop the same problem from recurring in the future
thanks in advance
The IndexOf call on line 32 returns -1 if the search string is not found. Presumably the data from the client doesn't contain "$".
String.Substring(int, int) expects a starting index in the first parameter and a length in the second parameter. IndexOf will return -1 if the search string is not found in the supplied string.
So your code:
dataFromClient.Substring(0, dataFromClient.IndexOf("$"))
Is looking for "$" in the string. If dataFromClient doesn't contain a "$", IndexOf returns -1, which then makes the Substring look like this:
dataFromClient.Substring(0, -1)
The documentation (linked above) states that an ArgumentOutOfRangeException is thrown when startIdnex plus length indicates a position not within this instance or startIndex or length is less than zero.
The length must be greater than 0, and -1 obviously is not. Hence the error.

using sockets to chat in web app gives me an error

I Tried to use sockets in asp.net using C#.
The commented line in the client code gives me error.
The server code is running properly.
This is the Client Code which Gives error.
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Text;
public partial class _Default : System.Web.UI.Page
{
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
NetworkStream serverStream = default(NetworkStream);
string readData = null;
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Post_Click(object sender, EventArgs e)
{
if (txtmsg.Text != "")
{
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(txtmsg.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
// This line gives error Saying Object reference not set to an instance of an object.
serverStream.Flush();
}
}
protected void Connect_Click(object sender, EventArgs e)
{
if (txtSub.Text != "")
{
try
{
readData = "Conected to Chat Server ...";
msg();
clientSocket.Connect("127.0.0.1", 8888);
serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(txtSub.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
Thread ctThread = new Thread(getMessage);
ctThread.Start();
}
catch
{
//Disconnect();
}
}
}
private void getMessage()
{
while (true)
{
serverStream = clientSocket.GetStream();
int buffSize = 0;
byte[] inStream = new byte[10025];
buffSize = clientSocket.ReceiveBufferSize;
serverStream.Read(inStream, 0, buffSize);
string returndata = System.Text.Encoding.ASCII.GetString(inStream);
readData = "" + returndata;
msg();
}
}
private void msg()
{
//if (this.InvokeRequired)
// this.Invoke(new MethodInvoker(msg));
//else
txtget.Text = txtget.Text + Environment.NewLine + " >> " + readData;
}
}
Your serverSteam object isn't being properly initialised and therefore causes an object error when you try to reference it.
You need to create a new NetworkSteam with a Socket object, and ensure that your Socket object is connected:
Socket my_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
..
// connect socket and any other operations
..
NetworkStream my_network_stream = new NetworkStream(my_socket);

How can I encrypt my message when sending to the server?

I would like to encrypt my message when sending to the server from client, how can I do it?
Client
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Threading;
namespace SocketClient
{
public partial class SocketClient : Form
{
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
NetworkStream serverStream = default(NetworkStream);
string readData = null;
public SocketClient()
{
InitializeComponent();
}
private void getMessage()
{
while (true)
{
serverStream = clientSocket.GetStream();
int buffSize = 0;
byte[] inStream = new byte[10025];
buffSize = clientSocket.ReceiveBufferSize;
serverStream.Read(inStream, 0, buffSize);
string returndata = System.Text.Encoding.ASCII.GetString(inStream);
readData = "" + returndata;
msg();
}
}
private void msg()
{
if (this.InvokeRequired)
this.Invoke(new MethodInvoker(msg));
else
textDisplay.Text = textDisplay.Text + Environment.NewLine + " >> " + readData;
}
private void buttonConnect_Click(object sender, EventArgs e)
{
readData = "Connected to NYP Chat Server ...";
msg();
//clientSocket.Connect("127.0.0.1", 8888);
clientSocket.Connect(textIP.Text, Convert.ToInt32(textPort.Text));
serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(textName.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
Thread ctThread = new Thread(getMessage);
ctThread.Start();
}
private void buttonSend_Click(object sender, EventArgs e)
{
// Show msg box if no server is connected
if (serverStream == null)
{
MessageBox.Show("Please connect to a server first!");
return;
}
// Send text
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(textSend.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
// Clear text
textSend.Text = "";
}
private void textDisplay_TextChanged(object sender, EventArgs e)
{
textDisplay.SelectionStart = textDisplay.Text.Length;
textDisplay.ScrollToCaret();
textDisplay.Refresh();
}
private void textSend_TextChanged(object sender, EventArgs e)
{
buttonSend.Enabled = !string.IsNullOrEmpty(textSend.Text);
}
}
}
server
using System;
using System.Threading;
using System.Net.Sockets;
using System.Text;
using System.Collections;
namespace ConsoleApplication1
{
class Program
{
public static Hashtable clientsList = new Hashtable();
static void Main(string[] args)
{
//TcpListener serverSocket = new TcpListener(portFromAppConfig);
TcpListener serverSocket = new TcpListener(9999);
TcpClient clientSocket = default(TcpClient);
int counter = 0;
serverSocket.Start();
Console.WriteLine("Welcome to NYP Chat Server ");
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 = System.Text.Encoding.ASCII.GetString(bytesFrom);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
clientsList.Add(dataFromClient, clientSocket);
broadcast(dataFromClient + " Connected ", dataFromClient, false);
Console.WriteLine(dataFromClient + " has join the chat room ");
handleClient client = new handleClient();
client.startClient(clientSocket, dataFromClient, clientsList);
}
clientSocket.Close();
serverSocket.Stop();
Console.WriteLine("exit");
Console.ReadLine();
}
public static void broadcast(string msg, string uName, bool flag)
{
foreach (DictionaryEntry Item in clientsList)
{
TcpClient broadcastSocket;
broadcastSocket = (TcpClient)Item.Value;
NetworkStream broadcastStream = broadcastSocket.GetStream();
Byte[] broadcastBytes = null;
if (flag == true)
{
broadcastBytes = Encoding.ASCII.GetBytes(uName + " says : " + msg);
}
else
{
broadcastBytes = Encoding.ASCII.GetBytes(msg);
}
broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
broadcastStream.Flush();
}
} //end broadcast function
}//end Main class
public class handleClient
{
TcpClient clientSocket;
string clNo;
Hashtable clientsList;
public void startClient(TcpClient inClientSocket, string clineNo, Hashtable cList)
{
this.clientSocket = inClientSocket;
this.clNo = clineNo;
this.clientsList = cList;
Thread ctThread = new Thread(doChat);
ctThread.Start();
}
private void doChat()
{
int requestCount = 0;
byte[] bytesFrom = new byte[10025];
string dataFromClient = null;
Byte[] sendBytes = null;
string serverResponse = null;
string rCount = null;
requestCount = 0;
while ((true))
{
try
{
requestCount = requestCount + 1;
NetworkStream networkStream = clientSocket.GetStream();
networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
Console.WriteLine("From client - " + clNo + " : " + dataFromClient);
rCount = Convert.ToString(requestCount);
Program.broadcast(dataFromClient, clNo, true);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}//end while
}//end doChat
} //end class handleClient
}//end namespace
Absolute simplest way is to rip all the code you wrote and just use WCF.
Next simplest way is to use a secure stream instead of the raw Network Stream, like SslStream or NegotiateStream. There a full blown sample at Secure Streams Sample that shows both the client and the server for NTLM/Kerberos and SChannel protocols (aka SSL/TLS).
One thing you should absolutely not do is write your own encryption. Encrypting messages is trivial and you'll find a myriad samples on the web. But creating a key exchange protocol so you actually have something to encrypt with is one of the hardest tasks in crypto. Use one of the industry acknowledged key exchange schemes like Kerberos or SSL/TLS, and these are already implemented in the two stream classes I linked.
C# provides a namespace for cryptography System.Security.Cryptography... for start you could check that out... Or try to implement a cryptography algorithm like Vernamm which is the simplest and easiest to implement. Or if you want to be fully secured you should use both the System.Security.Cryptography namespace the System.Security.Cryptography.X509Certificates namespace.

Categories