So my server and chat client are made from 2 different C# TCP tutorials.You may recognize 1 if not both of them and I have made my own modifications to them to fit my own style. When I tried both they worked perfectly fine with 0 loss, but my version has exactly a 50% loss rate. For instance: 1. A client connects: Data received 2. A client sends text: No Data 3. A client sends text: Data received 4. A client sends text: No Data The server code is as follows:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
namespace WindowsFormsApplication2
{
class Server
{
private TcpListener tcpListener;
private Thread listenThread;
public Hashtable clientsList = new Hashtable();
private System.Windows.Forms.TextBox output;
private delegate void ObjectDelegate(String text);
private ObjectDelegate del;
public Server(System.Windows.Forms.TextBox setOut)
{
this.tcpListener = new TcpListener(IPAddress.Any, 8888);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.IsBackground = true;
this.listenThread.Start();
output = setOut;
del = new ObjectDelegate(outputTextToServer);
}
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
addClient(client);
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.IsBackground = true;
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
String text = getData(clientStream);
del.Invoke(text); //Used for Cross Threading & sending text to server output
//if filter(text)
sendMessage(tcpClient);
//System.Diagnostics.Debug.WriteLine(text); //Spit it out in the console
}
tcpClient.Close();
}
private void outputTextToServer(String text)
{
if (output.InvokeRequired)
{
// we then create the delegate again
// if you've made it global then you won't need to do this
ObjectDelegate method = new ObjectDelegate(outputTextToServer);
// we then simply invoke it and return
output.Invoke(method, text);
return;
}
output.AppendText(Environment.NewLine + " >> " + text);
}
private String getData(NetworkStream stream)
{
int newData;
byte[] message = new byte[4096];
ASCIIEncoding encoder = new ASCIIEncoding();
newData = stream.Read(message, 0, 4096);
String text = encoder.GetString(message, 0, newData); //Translate it into text
text = text.Substring(0, text.IndexOf("$")); //Here comes the money
return text;
}
private void addClient(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
String dataFromClient = getData(clientStream);
if (clientsList.Contains(dataFromClient))
{
Console.WriteLine(dataFromClient + " Tried to join chat room, but " + dataFromClient + " is already in use");
//broadcast("A doppleganger of " + dataFromClient + " has attempted to join!", dataFromClient, false);
}
else
{
clientsList.Add(dataFromClient, tcpClient);
//broadcast(dataFromClient + " Joined ", dataFromClient, false);
del.Invoke(dataFromClient + " Joined chat room ");
//handleClinet client = new handleClinet();
//client.startClient(clientSocket, dataFromClient, clientsList);
}
}
private Boolean connectionAlive(NetworkStream stream)
{
byte[] message = new byte[4096];
int bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = stream.Read(message, 0, 4096);
}
catch
{
//a socket error has occured
return false;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
//clientsList.Remove
return false;
}
return true;
}
private void sendMessage(TcpClient client)
{
NetworkStream clientStream = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Client!");
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
}
}
And here's my client code
using System;
using System.Windows.Forms;
using System.Text;
using System.Net.Sockets;
using System.Threading;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public delegate void newDelegate();
public newDelegate myDelegate;
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
NetworkStream serverStream = default(NetworkStream);
string readData = null;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
newMsg();
}
private void newMsg()
{
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(textBox2.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
textBox2.Text = "";
}
private void button2_Click(object sender, EventArgs e)
{
readData = "Connecting to Chat Server ...";
msg();
clientSocket.Connect(txtIP.Text, int.Parse(txtPort.Text));
serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(txtName.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
myDelegate = new newDelegate(disconnect);
Thread ctThread = new Thread(getMessage);
ctThread.IsBackground = true;
ctThread.Start();
button2.Enabled = false;
}
private void getMessage()
{
while (true)
{
serverStream = clientSocket.GetStream();
int buffSize = 0;
byte[] inStream = new byte[clientSocket.ReceiveBufferSize];
buffSize = clientSocket.ReceiveBufferSize;
try
{
serverStream.Read(inStream, 0, buffSize);
string returndata = System.Text.Encoding.ASCII.GetString(inStream);
readData = "" + returndata;
msg();
}
catch
{
Invoke(myDelegate);
return;
}
}
}
private void disconnect()
{
button2.Enabled = true;
}
private void msg()
{
if (this.InvokeRequired)
this.Invoke(new MethodInvoker(msg));
else
textBox1.AppendText(Environment.NewLine + " >> " + readData);
//textBox1.Text = textBox1.Text + Environment.NewLine + " >> " + readData;
}
private void textBox2_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
newMsg();
}
}
private void cmdHost_Click(object sender, EventArgs e)
{
Server serv = new Server(txtLog);
}
}
}
This code is obviously a work in progress and sorry in advance for messiness. Any other suggestions to the code are also welcome.