I'm trying to send a file about 250 kb to server but i have a corruption and it seemd that tottaly transfered some bytes only. The flow of command is
Write to stream: Send\r\n
Write to stream: FileName\r\n
Write to stream: FileData \r\n
Close the connection
Here is the code:
TcpClient sendClient = new TcpClient(serverName, port);
SslStream sendStream = new SslStream(sendClient.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
try
{
sendStream.AuthenticateAsClient(serverName, null, SslProtocols.Ssl2, true);
sendStream.Write(Encoding.UTF8.GetBytes("Login\r\n" + username + "\r\n" + password + "\r\n"));
sendStream.Flush();
int bytesResp = -1;
byte[] buffer = new byte[1026];
bytesResp = sendStream.Read(buffer, 0, buffer.Length);
string response = Encoding.UTF8.GetString(buffer, 0, bytesResp);
if (response.Trim() == "OK")
{
byte[] fileNameByte = Encoding.UTF8.GetBytes(fileName + "\r\n");
byte[] fileData = File.ReadAllBytes(filePath);
byte[] newLine = Encoding.ASCII.GetBytes("\r\n");
byte[] clientData = new byte[4 + Encoding.ASCII.GetBytes("Send\r\n").Length + fileNameByte.Length + fileData.Length+newLine.Length];
byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);
byte[] send = Encoding.ASCII.GetBytes("Send\r\n");
send.CopyTo(clientData, 0);
fileNameLen.CopyTo(clientData, 4 + send.Length);
fileNameByte.CopyTo(clientData, send.Length);
fileData.CopyTo(clientData, 4 + fileNameByte.Length + send.Length);
newLine.CopyTo(clientData, 4+ fileNameByte.Length + send.Length + fileData.Length);
MessageBox.Show(clientData.Length.ToString());
sendStream.Write(clientData, 0, clientData.Length);
sendStream.Flush();
sendStream.Write(Encoding.UTF8.GetBytes("Quit\r\n"));
sendClient.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
Does anybody have an idea please?
You haven't told us about the other end of the connection, so this answer is partially speculative...
BitConverter.GetBytes(fileNameByte.Length); is likely to be a little-endian conversion.
Almost all network encoding will be big-endian, so this is a strong candidate for the failure.
I suggest you use the EndianBitConverter.Big converter from Jon Skeet's miscutil to get the proper encoding order.
I send file up to 1GB with this code
Server Code
using System;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.IO;
namespace Server_FileSend
{
public partial class Form1 : Form
{
Socket Server = null;
Socket Client = null;
Thread trStart;
Thread trRecive;
const int sizeByte = 1024;
public Form1()
{
InitializeComponent();
}
private void ReciveFile()
{
while (true)
{
try
{
byte[] b = new byte[sizeByte];
int rec = 1;
int vp = 0;
rec = Client.Receive(b);
int index;
for (index = 0; index < b.Length; index++)
if (b[index] == 63)
break;
string[] fInfo = Encoding.UTF8.GetString(b.Take(index).ToArray()).Split(':');
this.Invoke((MethodInvoker)delegate
{
progressBar1.Maximum = int.Parse(fInfo[0]);
});
string path = Application.StartupPath + "\\Downloads\\";
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
FileStream fs = new FileStream(path + fInfo[1], FileMode.Append, FileAccess.Write);
string strEnd;
while (true)
{
rec = Client.Receive(b);
vp = vp + rec;
strEnd = ((char)b[0]).ToString() + ((char)b[1]).ToString() + ((char)b[2]).ToString() + ((char)b[3]).ToString() + ((char)b[4]).ToString() + ((char)b[5]).ToString();
if (strEnd == "!endf!")
{
fs.Flush();
fs.Close();
MessageBox.Show("Receive File " + ((float)(float.Parse(fInfo[0]) / 1024)).ToString() + " KB");
break;
}
fs.Write(b, 0, rec);
this.Invoke((MethodInvoker)delegate
{
progressBar1.Value = vp;
});
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
Form1_FormClosing(null, null);
}
}
}
private void StartSocket()
{
Server.Listen(1);
Client = Server.Accept();
trRecive = new Thread(new ThreadStart(ReciveFile));
trRecive.Start();
}
private void Form1_Load(object sender, EventArgs e)
{
Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
IPEndPoint IP = new IPEndPoint(IPAddress.Any, 5050);
Server.Bind(IP);
trStart = new Thread(new ThreadStart(StartSocket));
trStart.Start();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
trRecive.Abort();
trStart.Abort();
Environment.Exit(Environment.ExitCode);
}
catch (Exception)
{
Environment.Exit(Environment.ExitCode);
}
}
}
}
Client Code
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace Clienf_fileSend
{
public partial class Form1 : Form
{
Socket Client = null;
Thread trRecive;
const int sizeByte = 1024;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
IPEndPoint IP = new IPEndPoint(IPAddress.Parse(textBox1.Text), 5050);
Client.Connect(IP);
button1.Enabled = false;
button2.Enabled = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void SendFile(object FName)
{
try
{
FileInfo inf = new FileInfo((string)FName);
progressBar1.Invoke((MethodInvoker)delegate
{
progressBar1.Maximum = (int)inf.Length;
progressBar1.Value = 0;
});
FileStream f = new FileStream((string)FName, FileMode.Open);
byte[] fsize = Encoding.UTF8.GetBytes(inf.Length.ToString() + ":");
byte[] fname = Encoding.UTF8.GetBytes(inf.Name + "?");
byte[] fInfo = new byte[sizeByte];
fsize.CopyTo(fInfo, 0);
fname.CopyTo(fInfo, fsize.Length);
Client.Send(fInfo);
if (sizeByte> f.Length)
{
byte[] b = new byte[f.Length];
f.Seek(0, SeekOrigin.Begin);
f.Read(b, 0, (int)f.Length);
Client.Send(b);
}
else
{
for (int i = 0; i < (f.Length - sizeByte); i = i + sizeByte)
{
byte[] b = new byte[sizeByte];
f.Seek(i, SeekOrigin.Begin);
f.Read(b, 0, b.Length);
Client.Send(b);
progressBar1.Invoke((MethodInvoker)delegate
{
progressBar1.Value = i;
});
if (i + sizeByte >= f.Length - sizeByte)
{
progressBar1.Invoke((MethodInvoker)delegate
{
progressBar1.Value = (int)f.Length;
});
int ind = (int)f.Length - (i + sizeByte);
byte[] ed = new byte[ind];
f.Seek(i + sizeByte, SeekOrigin.Begin);
f.Read(ed, 0, ed.Length);
Client.Send(ed);
}
}
}
f.Close();
Thread.Sleep(1000);
Client.Send(Encoding.UTF8.GetBytes("!endf!"));
Thread.Sleep(1000);
MessageBox.Show("Send File " + ((float)inf.Length / 1024).ToString() + " KB");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void button2_Click(object sender, EventArgs e)
{
OpenFileDialog fdl = new OpenFileDialog();
if (fdl.ShowDialog() == DialogResult.OK)
{
trRecive = new Thread(new ParameterizedThreadStart(SendFile));
trRecive.Start(fdl.FileName);
}
fdl = null;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
trRecive.Abort();
Environment.Exit(Environment.ExitCode);
}
catch (Exception)
{
Environment.Exit(Environment.ExitCode);
}
}
}
}
Related
Please bear in mind I am new to C# language and networking so forgive me if this might sound obvious.
I'm just in the process of understanding TCP clients and how to separate streams...
In this example, I have 3 sets of data that I want to send...
is a CMD output:
private void CmdOutputDataHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
StringBuilder strOutput = new StringBuilder();
if (!String.IsNullOrEmpty(outLine.Data))
{
try
{
strOutput.Append(outLine.Data);
buffer = encoder.GetBytes("2 " + outLine.Data+ "\r\n");
networkStream = newclient.GetStream();
networkStream.Write(buffer, 0, buffer.Length);
networkStream.Flush();
}
catch (Exception err) { }
}
}
Which returns as a first stream the following:
With a prebuffer as number 2(To separate the data)
The second Is a simple get info:
private void GetClientinfo()
{
networkStream = newclient.GetStream();
buffer = encoder.GetBytes("1 " + Environment.MachineName +"\n"+"Connected");
networkStream.Write(buffer, 0, buffer.Length);
networkStream.Flush();
}
Which then sends the following :
So then my stream ends up being separated:
My issue is then that I try to send a file with the following script:
private void sendFile()
{
// Create the preBuffer data.
string string1 = String.Format("9 ");
byte[] preBuf = Encoding.ASCII.GetBytes(string1);
// Create the postBuffer data.
string string2 = String.Format("");
byte[] postBuf = Encoding.ASCII.GetBytes(string2);
string filePath = #"\Users\nico_\Documents\transfer_ex.txt";
newclient.Client.SendFile(filePath, preBuf, postBuf, TransmitFileOptions.UseDefaultWorkerThread);
}
As you can see, it ends up getting jumbled up with the second stream being sent...
What would be the cause of this?
FULL SERVER SCRIPT:
public partial class Form1 : Form
{
TcpListener tcpListener = new TcpListener(System.Net.IPAddress.Any, 6666);
private int appStatus = 0;
TcpClient client;
TcpClient streamData;
List<TcpClient> clientList = new List<TcpClient>();
NetworkStream networkStream;
Thread th_StartListen, th_handleClient;
StringBuilder strOutput;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
th_StartListen = new Thread(new ThreadStart(StartListen));
th_StartListen.Start();
txtCmdOutput.Focus();
}
private void StartListen()
{
//Creating a TCP Connection and listening to the port
tcpListener = new TcpListener(System.Net.IPAddress.Any, 6666);
tcpListener.Start();
toolStripStatusLabel1.Text = "Listening on port 6666 ...";
int counter = 0;
appStatus = 0;
while (appStatus != 2)
{
try
{
client = tcpListener.AcceptTcpClient();
counter++;
clientList.Add(client);
IPEndPoint ipend = (IPEndPoint)client.Client.RemoteEndPoint;
//Updating status of connection
toolStripStatusLabel1.Text = "Connected from "+ IPAddress.Parse(ipend.Address.ToString());
appStatus = 1;
th_handleClient = new Thread(delegate () { handleClient(client, counter); });
th_handleClient.Start();
}
catch (Exception err)
{
{
Cleanup();
}
}
}
}
private void handleClient(object client, int i)
{
try
{
TcpClient streamData = (TcpClient)client;
byte[] data = new byte[4096];
byte[] sendData = new byte[4096];
int byteRead;
string strdata;
ASCIIEncoding encode = new ASCIIEncoding();
Thread.Sleep(2000);
NetworkStream networkstream = streamData.GetStream();
//Send Command 1
sendData = encode.GetBytes("1");
networkstream.Write(sendData, 0, sendData.Length);
networkstream.Flush();
//Listen...
while (true)
{
byteRead = 1;
byteRead = networkstream.Read(data, 0, 4096);
//receiveFile();
if (networkstream.DataAvailable != true)
{
strdata = Encoding.ASCII.GetString(data, 0, byteRead);
Debug.WriteLine(strdata);
//Get user info
if (strdata.StartsWith("1"))
{
updateLabel(labelMachinename, strdata, 0);
updateLabel(labelSampleOutput, strdata, 1);
}
if (strdata.StartsWith("2"))
{
updateText(txtCmdConsole, strdata);
}
if (strdata.StartsWith("9"))
{
Debug.WriteLine(strdata);
}
//receiveFile();
}
}
}
catch (Exception err)
{
{
Cleanup();
}
}
}
private void receiveFile()
{
StreamReader reader = new StreamReader(client.GetStream());
string fileSize = reader.ReadLine();
string fileName = reader.ReadLine();
int length = Convert.ToInt32(fileSize);
byte[] buffer = new byte[length];
int received = 0;
int read = 0;
int size = 1024;
int remaining = 0;
while (received < length)
{
remaining = length - received;
if (remaining < size)
{
size = remaining;
}
read = client.GetStream().Read(buffer, received, size);
received += read;
}
// Save the file using the filename sent by the client
using (FileStream fStream = new FileStream(Path.GetFileName(fileName), FileMode.Create))
{
fStream.Write(buffer, 0, buffer.Length);
fStream.Flush();
fStream.Close();
}
Debug.WriteLine("File received and saved in " + Environment.CurrentDirectory);
}
private void txtCmdOutput_KeyDown(object sender, KeyEventArgs e)
{
try
{
if (e.KeyCode == Keys.Enter && appStatus == 1)
{
TcpClient streamData = (TcpClient)client;
byte[] sendData = new byte[4096];
ASCIIEncoding encode = new ASCIIEncoding();
NetworkStream networkstream = streamData.GetStream();
sendData = encode.GetBytes("2 "+ txtCmdOutput.Text.ToString());
networkstream.Write(sendData, 0, sendData.Length);
networkstream.Flush();
txtCmdOutput.Text = "";
}
}
catch (Exception err) {
{
Cleanup();
}
}
}
private void updateLabel(Label label,string strdata, int row)
{
label.Invoke((MethodInvoker)delegate
{
label.Text = strdata.Substring(2).Split(new char[] { '\r', '\n' })[row];
});
}
private void updateText(TextBox text, string strdata)
{
text.Invoke((MethodInvoker)delegate
{
text.AppendText(strdata.Substring(2));
});
}
private void btnKillClient_Click(object sender, EventArgs e)
{
try
{
TcpClient streamData = (TcpClient)client;
byte[] sendData = new byte[4096];
ASCIIEncoding encode = new ASCIIEncoding();
NetworkStream networkstream = streamData.GetStream();
sendData = encode.GetBytes("3");
networkstream.Write(sendData, 0, sendData.Length);
networkstream.Flush();
Cleanup();
}
catch (Exception err)
{
{
Cleanup();
}
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
System.Environment.Exit(System.Environment.ExitCode);
}
private void Cleanup()
{
try
{
toolStripStatusLabel1.Text = "Connection Lost";
}
catch (Exception err) { }
}
}
FULL CLIENT SCRIPT:
public partial class Form1 : Form
{
private int appStatus = 0;
TcpClient newclient = new TcpClient();
NetworkStream networkStream;
byte[] buffer = new byte[4096];
ASCIIEncoding encoder = new ASCIIEncoding();
Process processCmd;
Thread th_ListenToServer, th_RunServer;
public Form1()
{
InitializeComponent();
}
private void Form1_Shown(object sender, EventArgs e)
{
this.Hide();
th_ListenToServer = new Thread(new ThreadStart(ListenToServer));
th_ListenToServer.Start();
//ConnectToServer();
}
private void ListenToServer()
{
while (!newclient.Connected)
{
try
{
newclient = new TcpClient();
Debug.WriteLine("trying to connect...");
newclient = new TcpClient("127.0.0.1", 6666);
networkStream = newclient.GetStream();
th_RunServer = new Thread(new ThreadStart(RunServer));
th_RunServer.Start();
}
catch (Exception ex)
{
Debug.WriteLine("Could not connect to server");
System.Threading.Thread.Sleep(5000); //Wait 5 seconds then try again
}
}
}
private void RunServer()
{
byte[] data = new byte[4096];
int i;
string strdata;
i = 0;
CmdHandler();
sendFile();
while (newclient.Connected)
{
try
{
i = 0;
i = networkStream.Read(data, 0, data.Length);
if (i == 0) { break; }
strdata = Encoding.ASCII.GetString(data, 0, i);
Debug.WriteLine(strdata);
if (strdata == "1")
{
GetClientinfo();
}
if (strdata.StartsWith("2"))
{
//Debug.WriteLine(strdata);
processCmd.StandardInput.WriteLine(strdata.Substring(2));
}
if (strdata.StartsWith("3"))
{
StopServer();
}
if (strdata.StartsWith("4"))
{
StopServer();
}
else
{
//sendFile();
}
}
catch
{
Cleanup();
new Thread(ListenToServer).Start();
Debug.WriteLine("Attempting Reconection");
}
}
}
private void sendFile()
{
/*
// Create the preBuffer data.
string fileName = #"\Users\nico_\Documents\transfer_ex.txt";
byte[] fileNameByte = Encoding.ASCII.GetBytes(fileName);
byte[] fileNameLen= BitConverter.GetBytes(fileNameByte.Length);
byte[] fileData = File.ReadAllBytes(fileName);
byte[] clientData = new byte[4 + fileNameByte.Length + fileData.Length];
fileNameLen.CopyTo(clientData, 0);
fileNameByte.CopyTo(clientData, 4);
fileData.CopyTo(clientData, 4 + fileNameByte.Length);
networkStream = newclient.GetStream();
buffer = encoder.GetBytes("9 " + clientData);
networkStream.Write(buffer, 0, buffer.Length);
networkStream.Flush();
*/
string string1 = String.Format("9 ");
byte[] preBuf = Encoding.ASCII.GetBytes(string1);
// Create the postBuffer data.
string string2 = String.Format("");
byte[] postBuf = Encoding.ASCII.GetBytes(string2);
string filePath = #"\Users\nico_\Documents\transfer_ex.txt";
newclient.Client.SendFile(filePath, preBuf, postBuf, TransmitFileOptions.UseDefaultWorkerThread);
}
private void GetClientinfo()
{
networkStream = newclient.GetStream();
buffer = encoder.GetBytes("1 " + Environment.MachineName + "\n" + "Connected");
networkStream.Write(buffer, 0, buffer.Length);
networkStream.Flush();
}
private void CmdHandler()
{
processCmd = new Process();
processCmd.StartInfo.FileName = "cmd.exe";
processCmd.StartInfo.CreateNoWindow = true;
processCmd.StartInfo.UseShellExecute = false;
processCmd.StartInfo.RedirectStandardOutput = true;
processCmd.StartInfo.RedirectStandardInput = true;
processCmd.StartInfo.RedirectStandardError = true;
//processCmd.OutputDataReceived += CaptureOutput;
//processCmd.ErrorDataReceived += CaptureError;
processCmd.OutputDataReceived += new DataReceivedEventHandler(CmdOutputDataHandler);
processCmd.ErrorDataReceived += new DataReceivedEventHandler(CmdOutputDataHandler);
processCmd.Start();
processCmd.BeginOutputReadLine();
}
private void CmdOutputDataHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
StringBuilder strOutput = new StringBuilder();
if (!String.IsNullOrEmpty(outLine.Data))
{
try
{
strOutput.Append(outLine.Data);
buffer = encoder.GetBytes("2 " + outLine.Data + "\r\n");
networkStream = newclient.GetStream();
networkStream.Write(buffer, 0, buffer.Length);
networkStream.Flush();
}
catch (Exception err) { }
}
}
private void Cleanup()
{
try { processCmd.Kill(); } catch (Exception err) { };
networkStream.Close();
}
private void StopServer()
{
Cleanup();
System.Environment.Exit(System.Environment.ExitCode);
}
}
Your first output appends \r\n, which results in separation from the second output. The second output embeds a \n (not \r\n) and ends with nothing, which means nothing separates it from the third output.
Either add a newline after data in GetClientInfo, or add one to preBuf in sendFile().
Or switch to something less ambiguous, like length-prefixing.
Here is the answer:
CLIENT SIDE:
private void sendFile()
{
string string1 = "9";
byte[] preBuf = Encoding.ASCII.GetBytes(string1);
// Create the postBuffer data.
string string2 = "";
byte[] postBuf = Encoding.ASCII.GetBytes(string2);
string filePath = #"\Users\nico_\Documents\transfer_ex.txt";
newclient.Client.SendFile(filePath, preBuf, postBuf, TransmitFileOptions.UseDefaultWorkerThread);
}
SERVER SIDE:
private void ReceiveFile(byte[] data, int byteRead)
{
var path = #"\Users\nico_\Documents\transferreeedd_ex.txt";
FileStream fs = File.OpenWrite(path);
//Debug.WriteLine(byteRead);
//Debug.WriteLine(data);
string ddstrdata = Encoding.ASCII.GetString(data, 0, byteRead);
for (int i = 1; i < byteRead; i++)
{
Debug.WriteLine(i);
fs.WriteByte(data[i]);
}
fs.Close();
}
If you dont use any separtators, on newclient.Client.SendFile you can just put the Filepath and on Server side int i = 0 & not int i = 1
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.
I have this tcp socket chat application from youtube
server side
int i;
TcpListener server = new TcpListener(IPAddress.Any, 1980);
NetworkStream stream;
TcpClient client;
byte[] datalength = new byte[4];
public Form1()
{
InitializeComponent();
}
public void ServerReceive()
{
stream = client.GetStream();
new Thread(() =>
{
while ((i = stream.Read(datalength, 0, 4)) != 0)
{
byte[] data = new byte[BitConverter.ToInt32(datalength, 0)];
stream.Read(data, 0, data.Length);
this.Invoke((MethodInvoker)delegate
{
txtLog.Text += System.Environment.NewLine + "Client : " + Encoding.Default.GetString(data);
});
}
}).Start();
}
public void ServerSend(string msg)
{
stream = client.GetStream();
byte[] data;
data = Encoding.Default.GetBytes(msg);
int length = data.Length;
byte[] datalength = new byte[4];
datalength = BitConverter.GetBytes(length);
stream.Write(datalength, 0, 4);
stream.Write(data, 0, data.Length);
}
private void btnSend_Click(object sender, EventArgs e)
{
try
{
if (client.Connected)
{
ServerSend(txtSend.Text);
}
}catch
{
txtLog.Text += "connection close";
}
}
private void btnListen_Click(object sender, EventArgs e)
{
server.Start();
new Thread(() =>
{
client = server.AcceptTcpClient();
if (client.Connected)
{
ServerReceive();
}
}).Start();
}
client side
int i;
TcpClient client;
NetworkStream stream;
byte[] datalength = new byte[4];
public Form1()
{
InitializeComponent();
}
public void ClientReceive()
{
stream = client.GetStream();
new Thread(() =>
{
while ((i = stream.Read(datalength, 0, 4)) != 0)
{
byte[] data = new byte[BitConverter.ToInt32(datalength, 0)];
stream.Read(data, 0, data.Length);
this.Invoke((MethodInvoker)delegate
{
txtLog.Text += System.Environment.NewLine + "Server : " + Encoding.Default.GetString(data);
});
}
}).Start();
}
public void ClientSend(string msg)
{
stream = client.GetStream();
byte[] data;
data = Encoding.Default.GetBytes(msg);
int length = data.Length;
byte[] datalength = new byte[4];
datalength = BitConverter.GetBytes(length);
stream.Write(datalength, 0, 4);
try
{
stream.Write(data, 0, data.Length);
}
catch
{
stream.Dispose();
client.Close();
}
}
private void btnConnect_Click(object sender, EventArgs e)
{
try
{
client = new TcpClient("127.0.0.1", 1980);
ClientReceive();
txtLog.Text += Environment.NewLine+ "Connected";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnSend_Click(object sender, EventArgs e)
{
if (client.Connected)
{
ClientSend(txtSend.Text);
}
}
now, all of these works fine for me, however everytime i close one them i get this error
'Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.' at ClientReceive() or ServerReceive()
how should i catch this error if one of them suddenly closed or the network cable suddenly unplug? thanks in advance
In this case, you're receiving a System.IO.IOException from the NetworkStream object. This exception has a nested System.Net.Sockets.SocketException with an ErrorCode of 10054 (SocketErrorCode == ConnectionReset). To handle the exception, use a try-catch block. For example,
using System;
using System.IO;
using System.Net.Sockets;
stream = client.GetStream();
new Thread(() =>
{
try
{
while ((i = stream.Read(datalength, 0, 4)) != 0)
{
byte[] data = new byte[BitConverter.ToInt32(datalength, 0)];
stream.Read(data, 0, data.Length);
this.Invoke((MethodInvoker)delegate
{
txtLog.Text += System.Environment.NewLine + "Server : " + Encoding.Default.GetString(data);
});
}
}
catch (IOException ioex)
{
if (ioex.InnerException != null)
{
var sex = ex.InnerException as SocketException;
if (sex == null)
{
txtLog.Text += Environment.NewLine + "An unknown exception occurred.";
}
else
{
switch (sex.SocketErrorCode)
{
case SocketError.ConnectionReset:
txtLog.Text += Environment.NewLine + "A ConnectionReset SocketException occurred."
break;
default:
txtLog.Text += Environment.NewLine + "A SocketException occurred.";
break;
}
}
}
else
{
txtLog.Text += Environment.NewLine + "An IOException occurred.";
}
}
}).Start();
I am transferring file via socket programming in C# with the code given below. But when I take pdf as input file, it is not received correctly. I have seen sent and received files in notepad, they are not same.
I am not able to figure it out. any help appreciated !!!
Server Code:
class ConnectionInfo
{
public Socket Socket;
public byte[] Buffer;
public int client;
public string fileName;
}
class Program
{
static int chunkSize = 16 * 1024;
static int chucksizeWithoutHeaderData = chunkSize - 8;
static List<ConnectionInfo> list = new List<ConnectionInfo>();
static Socket serverSocket;
static int nClient = 0;
static void AcceptCallback(IAsyncResult result)
{
ConnectionInfo info = new ConnectionInfo();
info.Socket = serverSocket.EndAccept(result);
info.Buffer = new byte[chunkSize * 4];
Console.WriteLine("Client connected");
nClient++;
info.client = nClient;
list.Add(info);
info.Socket.BeginReceive(info.Buffer, 0, info.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), info);
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
static void ReceiveCallBack(IAsyncResult result)
{
ConnectionInfo info = result.AsyncState as ConnectionInfo;
try
{
Int32 nSegmentNumber = BitConverter.ToInt32(info.Buffer, 0);
Int32 nMaxSegment = BitConverter.ToInt32(info.Buffer, 4);
string strFileName = string.Format(#"D:\xyz.pdf", info.client);
//int bySize = info.Socket.EndReceive(result);
int bySize = 0;
try
{
bySize = info.Socket.EndReceive(result);
}
catch (Exception ex)
{
Console.WriteLine("Error from client {0}: {1}", info.client, ex.Message);
return;
}
if (bySize <= 0)
{
return;
}
using (FileStream fs = new FileStream(strFileName, FileMode.OpenOrCreate))
{
Console.WriteLine("Received segment {0} of {1} from client {2}", nSegmentNumber, nMaxSegment, info.client);
fs.Position = fs.Length;
fs.Write(info.Buffer, 8, bySize - 8);
Console.Write("Content in FILE: " + Encoding.ASCII.GetString(info.Buffer));
if (nSegmentNumber >= nMaxSegment)
{
Console.WriteLine("Completed receipt from client {0}", info.client);
}
}
info.Socket.BeginReceive(info.Buffer, 0, info.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), info);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
static void Main(string[] args)
{
try
{
Console.WriteLine("Server");
IPAddress address = IPAddress.Parse("127.0.0.1"); //The IP address of the server
IPEndPoint myEndPoint = new IPEndPoint(address, 6503);
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Bind(myEndPoint);
serverSocket.Listen(1000);
Console.WriteLine("Press enter to end server");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex);
Console.ReadLine();
}
}
}
Client code:
class Program
{
static TcpClient socket = new TcpClient();
static int chunkSize = 16 * 1024;
static int chucksizeWithoutHeaderData = chunkSize - 8;
static byte[] byReceiveBuffer = new byte[chunkSize * 4];
static void ReceiveCallBack(IAsyncResult result)
{
Socket socket = result.AsyncState as Socket;
try
{
int bySize = socket.EndReceive(result);
Console.WriteLine("Recieved bytes {0}", bySize);
if (bySize != 0)
{
Int32 nSegmentNumber = BitConverter.ToInt32(byReceiveBuffer, 0);
Int32 nMaxSegment = BitConverter.ToInt32(byReceiveBuffer, 4);
Console.WriteLine("Received segment {0} of {1}", nSegmentNumber, nMaxSegment);
string strFileName = string.Format(#"c:\temp\client-from-server.dat");
using (FileStream fs = new FileStream(strFileName, FileMode.OpenOrCreate))
{
fs.Position = fs.Length;
fs.Write(byReceiveBuffer, 8, bySize - 8);
}
if (nSegmentNumber >= nMaxSegment)
{
Console.WriteLine("all done");
}
}
socket.BeginReceive(byReceiveBuffer, 0, byReceiveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), socket);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
static void Main(string[] args)
{
Console.WriteLine("Press enter to go");
Console.ReadLine();
socket.Connect("127.0.0.1", 6503);
Console.WriteLine("Client");
Console.ReadLine();
string filePath = "";
string fileName = "C:\\abc.pdf";
//fileName = fileName.Replace("\\", "/");
while (fileName.IndexOf("\\") > -1)
{
filePath += fileName.Substring(0, fileName.IndexOf("\\") + 1);
fileName = fileName.Substring(fileName.IndexOf("\\") + 1);
}
byte[] byBuffer;
using (FileStream fs = new FileStream(#filePath+fileName, FileMode.Open, FileAccess.Read, FileShare.None))
{
using (BinaryReader br = new BinaryReader(fs))
{
int nMaxChunk = 0;
int nCurrentChunk = 0;
nMaxChunk = (int)(fs.Length / chucksizeWithoutHeaderData);
if ((nMaxChunk * chucksizeWithoutHeaderData) < fs.Length)
{
++nMaxChunk;
}
byte[] byMaxChunk = BitConverter.GetBytes(nMaxChunk);
Int64 nAmount = 0;
while (fs.Length > nAmount)
{
++nCurrentChunk;
byte[] byCurrentChunk = BitConverter.GetBytes(nCurrentChunk);
byBuffer = br.ReadBytes(chucksizeWithoutHeaderData);
Console.WriteLine("Sending {0}bytes, chunk {1} of {2}", byBuffer.Length, nCurrentChunk, nMaxChunk);
byte[] byTransmitBuffer = new byte[byBuffer.Length + 8];
Array.Copy(byCurrentChunk, byTransmitBuffer, 4);
Array.Copy(byMaxChunk, 0, byTransmitBuffer, 4, 4);
Array.Copy(byBuffer, 0, byTransmitBuffer, 8, byBuffer.Length);
socket.Client.Send(byTransmitBuffer);
nAmount += byBuffer.Length;
}
}
}
socket.Client.Disconnect(false);
Console.WriteLine("done");
Console.ReadLine();
}
}
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.