How To Send A File By Sockets On TCP Protocol In C#? - c#

I have a serious problem with this code. This is how it should work:
Client connects to server and choose a file on disk. after that client sends a (byte[] buffer) to the server by this format("File" (4 bytes) + FileNameLength (4 bytes) + FileDataLength (4 bytes)).
After that server creates a (byte[] buffer) with this size (new byte[FileNameLength + FileDataLength]).So client sends a data to the server by this format(byte[] buffer = FileName + FileData). And the server gets a file. The problem is here that i have a MessageBox in the Server to see the FileName after receiving that but MessageBox is always blank and it runs times and times and times.
what's the solution?
The Server:
private Socket SServer = null;
private Socket SClient = null;
private byte[] buffer = new byte[1024];
private byte[] FileNameLength = null;
private byte[] FileSize = null;
private void Server_Load(object sender, EventArgs e)
{
SServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
SServer.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 13000));
SServer.Listen(1);
new Thread(() =>
{
SClient = SServer.Accept();
MessageBox.Show("Connected.");
new Thread(() => Receiver()).Start();
}).Start();
}
private void Receiver()
{
buffer = new byte[1024];
while (true)
{
Int32 AllLength = SClient.Receive(buffer, 0, buffer.Length, SocketFlags.None);
byte[] Devider = new byte[4];
Array.Copy(buffer, 0, Devider, 0, 4);
string Devide = Encoding.ASCII.GetString(Devider);
if (AllLength > 0)
{
if (Devide == "File")
{
FileNameLength = new byte[4];
Array.Copy(buffer, 4, FileNameLength, 0, 4);
FileSize = new byte[4];
Array.Copy(buffer, 8, FileSize, 0, 4);
buffer = null;
buffer = new byte[BitConverter.ToInt32(FileNameLength, 0) + BitConverter.ToInt32(FileSize, 0)];
}
else
{
byte[] FileNameBytes = new byte[BitConverter.ToInt32(FileNameLength, 0)];
Array.Copy(buffer, 0, FileNameBytes, 0, BitConverter.ToInt32(FileNameLength, 0));
byte[] FileBytes = new byte[BitConverter.ToInt32(FileSize, 0)];
Array.Copy(buffer, BitConverter.ToInt32(FileNameLength, 0), FileBytes, 0, BitConverter.ToInt32(FileBytes, 0));
string FileName = Encoding.ASCII.GetString(FileNameBytes);
MessageBox.Show(FileName);
buffer = null;
buffer = new byte[1024];
}
}
}
}
TheClient:
private Socket SClient = null;
string Path, FileName;
private void Client_Load(object sender, EventArgs e)
{
SClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
SClient.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 13000));
}
private void BT_SendFile_Click(object sender, EventArgs e)
{
byte[] FileLengthBytes = BitConverter.GetBytes(FileName.Length);
byte[] FileBytes = File.ReadAllBytes(Path + FileName);
byte[] buffer = new byte[FileLengthBytes.Length + FileBytes.Length + 4];
//buffer = Encoding.Unicode.GetBytes("File") + FileLengthBytes + FileBytes;
Array.Copy(Encoding.ASCII.GetBytes("File"), 0, buffer, 0, 4);
Array.Copy(FileLengthBytes, 0, buffer, 4, FileLengthBytes.Length);
Array.Copy(BitConverter.GetBytes(FileBytes.Length), 0, buffer, 8, 4);
SClient.Send(buffer, 0, buffer.Length, SocketFlags.None);
byte[] FileNameBytes = Encoding.ASCII.GetBytes(FileName);
buffer = null;
buffer = new byte[FileNameBytes.Length + FileBytes.Length];
Array.Copy(FileNameBytes, 0, buffer, 0, FileNameBytes.Length);
Array.Copy(FileBytes, 0, buffer, FileNameBytes.Length, FileBytes.Length);
SClient.Send(buffer, 0, buffer.Length, SocketFlags.None);
}
private void BT_Browse_Click(object sender, EventArgs e)
{
OpenFileDialog N = new OpenFileDialog();
if (N.ShowDialog() == DialogResult.OK)
{
TB_Address.Text = N.FileName;
string[] Seperate = N.FileName.Split('\\');
FileName = Seperate[Seperate.Length - 1];
Path = null;
foreach (string str in Seperate)
{
if (str != Seperate[Seperate.Length - 1])
Path += str + "\\";
}
}
}

as this friend (Fildor) said, i try to read more about the protocols.
thank you two guys but i think if i separate the file and send it pieces by pieces, i can send the hole file.
I know maybe this is stupid but i think it works.

Related

C# TCP Socket Stream read wrong bytes

I Read Stream with:
private Stream _Stream;
private Socket _Socket;//TCP Socket
private void ReadStream()
{
if (Guest)
{
var sizeBuffer = ReadBytes(2);//the size buffer is always 2
int size = sizeBuffer[1];
size |= (sizeBuffer[0] << 8);
var data = ReadBytes(size);
string payload = System.Text.Encoding.UTF8.GetString(data, 0, data.Length);
var tokens = SplitPayload(payload);
if (tokens[0] == "nick")
{
SetNick(tokens);
}
else
{
throw new ApplicationException("Set your nick first");
}
}
else if(!Guest)
{
var sizeBuffer = ReadBytes(2);
int size = sizeBuffer[1];
size |= (sizeBuffer[0] << 8);
var data = ReadBytes(size);
string payload = System.Text.Encoding.UTF8.GetString(data, 0, data.Length);
var tokens = SplitPayload(payload);
CheckToken(tokens);
}
if (encrypted == null)
{
encrypted = false;
byte[] sizebuffer = new byte[2];
var size = _Socket.Receive(sizebuffer);
byte[] data = new byte[size];
var datasize = _Socket.Receive(data);
if (data[0] == 0x01)
{
encrypted = true;
_Stream = new NetworkStream(_Socket, true);
var sslStream = new SslStream(_Stream, false);
serverCertificate = new X509Certificate2(Path, "");
sslStream.AuthenticateAsServer(serverCertificate);
_Stream = sslStream;
}
else
{
encrypted = false;
_Stream = new NetworkStream(_Socket, true);
}
}
}
I write to the stream with:
private void SendServerMsg(string[] arguments)
{
var msg = string.Join("\0", arguments);
byte[] data = Encoding.UTF8.GetBytes(msg);
byte[] sizeinfo = new byte[2];
sizeinfo[1] = (byte)data.Length;
sizeinfo[0] = (byte)(data.Length >> 8);
_Stream.Write(sizeinfo, 0, sizeinfo.Length);
_Stream.Write(data, 0, data.Length);
}
my Problem is now:
1. When I make a Breakpoint at the line
_Stream.Write(sizeinfo, 0, sizeinfo.Length);
and step through manualy all work. The TCP _Socket gets the correct bytes,
but with no breakpoint the server stucks in the line
var data = ReadBytes(size);
and the size is more than 5000 but I send not more than 15 bytes (for example: "nick\0test")
hear is the readBytes method
private byte[] ReadBytes(int count)
{
byte[] buffer = new byte[count];
for (var i = 0; i < count; i++)
{
var oneByte = _Stream.ReadByte();
if (oneByte == -1)
{
break;
}
buffer[i] = (byte)oneByte;
}
return buffer;
}

Sending base64 string trough sockets doesnt completely arrive

In my application I wanted to implement profile pictures, so I started with a standard picture, which I converted to a byte array and then base64 string, however when the client requests the string from the server it doesnt fully arrive, the server reads the whole string from the database and sends it to the client, the client receives only a part of the string, this is the string(had to use pastebin): http://pastebin.com/ZmHhsZgG And this is the string the client receives: iVBORw0KGgoAAAANSUhEUgAAAEA
This is how the server gets it from the database:
public string GetPP(string user)
{
CONN = new MySqlConnection();
CONN.ConnectionString = Config.CONNSTRING;
string query = "select * from members where username='" + user + "'";
try
{
CONN.Open();
COMMAND = new MySqlCommand(query, CONN);
READER = COMMAND.ExecuteReader();
string p = null;
while (READER.Read())
{
return p = READER.GetString("profilepic");
}
return p;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return "";
}
finally
{
CONN.Dispose();
}
}
then it sends it:
private void Do()
{
int requestCount = 0;
byte[] bytesFrom = new byte[20025];
string dataFromClient = null;
Byte[] sendBytes = null;
string serverResponse = null;
string rCount = null;
requestCount = 0;
Responder.Responder R = new Responder.Responder();
while ((true))
{
try
{
byte[] buffer = new byte[4];
requestCount = requestCount + 1;
NetworkStream networkStream = clientSocket.GetStream();
buffer = new byte[4];
int readBytes = networkStream.Read(buffer, 0, 4);
if (readBytes == 0)
break;
int MessageSize = BitConverter.ToInt32(buffer, 0);
byte[] bufferreader = new byte[MessageSize];
readBytes = networkStream.Read(bufferreader, 0, MessageSize);
if (readBytes == 0)
break;
dataFromClient = Encoding.ASCII.GetString(bufferreader);
rCount = Convert.ToString(requestCount);
byte[] outbuffer = new byte[4];
serverResponse = R.Respond(dataFromClient);
sendBytes = Encoding.ASCII.GetBytes(serverResponse);
outbuffer = new byte[4];
outbuffer = BitConverter.GetBytes(sendBytes.Length);
networkStream.Write(buffer, 0, 4);
networkStream.Flush();
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
}
catch (Exception ex)
{
Console.WriteLine(" >> " + ex.ToString());
}
}
Console.WriteLine("User Server >> " + "Client No:" + Convert.ToString(clNo) + " Stopped!");
}
And the client receives:
byte[] inbuffer = new byte[4];
buffer = new byte[4];
int readBytes = serverStream.Read(buffer, 0, 4);
int MessageSize = BitConverter.ToInt32(buffer, 0);
Console.WriteLine(Convert.ToString(MessageSize));
byte[] bufferreader = new byte[MessageSize];
readBytes = serverStream.Read(bufferreader, 0, MessageSize);
string dataFromServer = Encoding.ASCII.GetString(bufferreader);
if (dataFromServer.Contains("reauth"))
{
MessageBox.Show("Session Expired! Please Re-authenticate..");
this.Close();
}
else
{
richTextBox1.Text = dataFromServer; //used to see what it receives
MemoryStream mStream = new MemoryStream();
byte[] pData = Convert.FromBase64String(dataFromServer);
mStream.Write(pData, 0, Convert.ToInt32(pData.Length));
Bitmap bm = new Bitmap(mStream, false);
mStream.Dispose();
pictureBox1.Image = bm;
}
clientSocket.Close();
Thanks in advance
I think the data isn't fully read because the 'buffer' variable which you send as the length indicator is not initialized to an updated value. I guess what you wanted to send was:
serverResponse = R.Respond(dataFromClient);
sendBytes = Encoding.ASCII.GetBytes(serverResponse);
outbuffer = new byte[4];
outbuffer = BitConverter.GetBytes(sendBytes.Length);
**networkStream.Write(outbuffer , 0, 4);**
networkStream.Flush();
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
NetworkStream.Read method returns the number of bytes successfully read.If you want to read whole data,you have to read several times.You can try follow codes:
private int read(NetworkStream ns, Byte[] data_buffer)
{
int result = -1;
const int kBufferSize = 1024 * 1024;
Byte[] buffer = new Byte[kBufferSize];
int read_size = 0;
int real_read_size = 0;
int read_length;
int total_length;
if (ns != null && data_buffer != null)
{
try
{
total_length = data_buffer.Length;
read_size = 0;
real_read_size = 0;
read_length = 0;
while (true)
{
read_size = kBufferSize <= (total_length - read_length) ? kBufferSize : total_length - read_length;
//todo:if (ns.CanRead)
real_read_size = ns.Read(buffer, 0, read_size);
if (real_read_size > 0)
{
Array.Copy(buffer, 0, data_buffer, read_length, real_read_size);
read_length += real_read_size;
//Console.WriteLine("net Read " + read_length.ToString() + " byte!");
if (read_length >= total_length)
{
result = 0;
break;
}
}
else
{
Console.WriteLine("net Read 0 byte!");
result = -1;
break;
}
}
}
catch (IOException e)
{
Console.WriteLine("SocketException: {0}", e);
}
finally
{
}
}
return result;
}

streamread can't read any data from NetworkStream in c# ,

I have a sensor that has an ip and port 192.168.2.44:3000.
I used the herculas to connect to the device ,as you can see in the picture :
enter image description here
I need to implement this software in c# ,so i write this code :
private static void Main(string[] args)
{
try
{
byte[] buffer = new byte[2048]; // read in chunks of 2KB
int bytesRead;
var listener = new TcpListener(IPAddress.Any, 3000);
listener.Start();
NetworkStream network_stream;
StreamReader read_stream;
StreamWriter write_stream;
var client = listener.AcceptTcpClient();
network_stream = client.GetStream();
read_stream = new StreamReader(network_stream);
write_stream = new StreamWriter(network_stream);
write_stream.WriteLine("00010002000B0300010004C380");
write_stream.Flush(); //veriyi gönderiyor
string gelen;
gelen = read_stream.ReadLine();
Console.WriteLine(gelen);
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.ReadLine();
}
}
When i put a breakpoint the gelen = read_stream.ReadLine(); returns null
http://www.hw-group.com/products/hercules/index_en.html
the final code :
class Program
{
static void Main(string[] args)
{
TcpListener server = null;
try
{
Int32 port = 3000;
// IPAddress localAddr = IPAddress.Parse(IPAddress.Any);
server = new TcpListener(IPAddress.Any, port);
server.Start();
// Buffer for reading data
Byte[] bytes = new Byte[256];
String data = null;
while (true)
{
Console.Write("Waiting for a connection... ");
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
data = null;
NetworkStream stream = client.GetStream();
byte[] aaa = { 0, 1, 0, 2, 0, 11, 3, 0, 1, 0, 4, 195, 128 };
stream.Write(aaa, 0, aaa.Length);
int i;
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);
data = data.ToUpper();
byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);
stream.Write(msg, 0, msg.Length);
Console.WriteLine("Sent: {0}", data);
}
client.Close();
}
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
finally
{
server.Stop();
}
Console.WriteLine("\nHit enter to continue...");
Console.Read();
}
}

C# Multi threaded Server

I have this client and server code.
Client:
namespace ClientTest
{
internal class Program
{
private static TcpClient client;
private static NetworkStream stream;
private static void Main(string[] args)
{
string temp;
client = new TcpClient("192.168.1.2",5052);
stream = client.GetStream();
Console.WriteLine(client.SendBufferSize);
while ((temp = Console.ReadLine()) != "exit")
{
Send(temp);
}
Thread one=new Thread(()=> SendFile(new FileInfo(#"1.doc")));
one.Start();
Thread two=new Thread(()=> SendFile(new FileInfo(#"2.docx")));
two.Start();
// Console.ReadKey(true);
}
public static void SendFile(FileInfo file)
{
stream = client.GetStream();
byte[] id = BitConverter.GetBytes((ushort)1);
byte[] size = BitConverter.GetBytes(file.Length);
byte[] fileName = Encoding.UTF8.GetBytes(file.Name);
byte[] fileNameLength = BitConverter.GetBytes((ushort)fileName.Length);
byte[] fileInfo = new byte[12 + fileName.Length];
id.CopyTo(fileInfo, 0);
size.CopyTo(fileInfo, 2);
fileNameLength.CopyTo(fileInfo, 10);
fileName.CopyTo(fileInfo, 12);
stream.Write(fileInfo, 0, fileInfo.Length); //Размер файла, имя
byte[] buffer = new byte[1024 * 32];
int count;
long sended = 0;
using (FileStream fileStream = new FileStream(file.FullName, FileMode.Open))
while ((count = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
stream.Write(buffer, 0, count);
sended += count;
Console.WriteLine("{0} bytes sended.", sended);
}
stream.Flush();
}
private static void Send(string message)
{
byte[] id = BitConverter.GetBytes((ushort)0);
byte[] msg = Encoding.UTF8.GetBytes(message);
byte[] msgLength = BitConverter.GetBytes((ushort)msg.Length);
byte[] fileInfo = new byte[12 + msg.Length];
id.CopyTo(fileInfo, 0);
msgLength.CopyTo(fileInfo, 10);
msg.CopyTo(fileInfo, 12);
stream.Write(fileInfo, 0, fileInfo.Length);
stream.Flush();
}
}
}
Server:
namespace Server_Test
{
class Server
{
static void Main(string[] args)
{
Server serv = new Server();
}
private TcpListener listener { get; set; }
private NetworkStream stream { get; set; }
public Server()
{
listener = new TcpListener(IPAddress.Parse("192.168.1.2"), 5052);
listener.Start();
new Thread(ListenForClients).Start();
}
private void ListenForClients()
{
while (true)
{
TcpClient client = this.listener.AcceptTcpClient();
new Thread(HandleClient).Start(client);
}
}
private void HandleClient(object tcpClient)
{
TcpClient client = (TcpClient)tcpClient;
while (client.Connected)
{
Recieve(client);
}
}
private void Recieve(TcpClient client)
{
byte[] buffer = new byte[client.ReceiveBufferSize];
try
{
stream = client.GetStream();
int bytesRead = stream.Read(buffer, 0, 12);
if (bytesRead == 0) return;
ushort id = BitConverter.ToUInt16(buffer, 0);
long len = BitConverter.ToInt64(buffer, 2);
ushort nameLen = BitConverter.ToUInt16(buffer, 10);
stream.Read(buffer, 0, nameLen);
string fileName = Encoding.UTF8.GetString(buffer, 0, nameLen);
if (id == 1)
{
using (BinaryWriter writer = new BinaryWriter(new FileStream(fileName, FileMode.Create)))
{
int recieved = 0;
while (recieved < len)
{
bytesRead = stream.Read(buffer, 0, client.ReceiveBufferSize);
recieved += bytesRead;
writer.Write(buffer, 0, bytesRead);
Console.WriteLine("{0} bytes recieved.", recieved);
}
}
Console.WriteLine("File length: {0}", len);
Console.WriteLine("File Name: {0}", fileName);
Console.WriteLine("Recieved!");
}
else
{
Console.WriteLine(fileName);
}
}
catch (Exception ex)
{
stream.Close();
client.Close();
Console.WriteLine(ex);
}
finally
{
stream.Flush();
}
}
}
}
The problem:i can't send 2 files in threads. If i send 1 file, server receives it and correctly saves.
What changes needed in this code to let client transfer 2 or more files and to let server receive it?
UDP. Added modified SendFile, but in doesn't work.
public static void SendFile(FileInfo file)
{
TcpClient client;
NetworkStream stream;
client = new TcpClient("192.168.1.2", 5052);
stream = client.GetStream();
byte[] id = BitConverter.GetBytes((ushort)1);
byte[] size = BitConverter.GetBytes(file.Length);
byte[] fileName = Encoding.UTF8.GetBytes(file.Name);
byte[] fileNameLength = BitConverter.GetBytes((ushort)fileName.Length);
byte[] fileInfo = new byte[12 + fileName.Length];
id.CopyTo(fileInfo, 0);
size.CopyTo(fileInfo, 2);
fileNameLength.CopyTo(fileInfo, 10);
fileName.CopyTo(fileInfo, 12);
stream.Write(fileInfo, 0, fileInfo.Length); //Размер файла, имя
byte[] buffer = new byte[1024 * 32];
int count;
long sended = 0;
using (FileStream fileStream = new FileStream(file.FullName, FileMode.Open))
while ((count = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
stream.Write(buffer, 0, count);
sended += count;
Console.WriteLine("{0} bytes sended.", sended);
}
}
On the client side, your two separate sending threads cannot share the same instance of client = new TcpClient("192.168.1.2",5052); to simultaneously send data. Each thread should have its own instance. Note, however, that it is fine for 2 client sockets to hit the same server-side IP:port simultaneously. It is just that the outbound port on the client-side has to be different between the 2 connections. When you create an additional outbound TCP connection on the client, the TcpClient will automatically use the next available outbound port.
For example, you could try something like the following:
internal class Program
{
private static void Main(string[] args)
{
SenderThreadClass stc1 = SenderThreadClass("192.168.1.2", 5052);
SenderThreadClass stc2 = SenderThreadClass("192.168.1.2", 5052);
Thread one = new Thread(()=> stc1.SendFile(new FileInfo(#"1.doc")));
one.Start();
Thread two = new Thread(()=> stc2.SendFile(new FileInfo(#"2.docx")));
two.Start();
}
}
public class SenderThreadClass
{
private TcpClient client;
private NetworkStream stream;
public SenderThreadClass(string serverIP, int serverPort)
{
client = new TcpClient(serverIP, serverPort);
stream = client.GetStream();
}
public void SendFile(FileInfo file)
{
byte[] id = BitConverter.GetBytes((ushort)1);
byte[] size = BitConverter.GetBytes(file.Length);
byte[] fileName = Encoding.UTF8.GetBytes(file.Name);
byte[] fileNameLength = BitConverter.GetBytes((ushort)fileName.Length);
byte[] fileInfo = new byte[12 + fileName.Length];
id.CopyTo(fileInfo, 0);
size.CopyTo(fileInfo, 2);
fileNameLength.CopyTo(fileInfo, 10);
fileName.CopyTo(fileInfo, 12);
stream.Write(fileInfo, 0, fileInfo.Length); //Размер файла, имя
byte[] buffer = new byte[1024 * 32];
int count;
long sended = 0;
using (FileStream fileStream = new FileStream(file.FullName, FileMode.Open))
while ((count = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
stream.Write(buffer, 0, count);
sended += count;
Console.WriteLine("{0} bytes sended.", sended);
}
stream.Flush();
}
}

Delay 3mins at the start of the program why? socket programming in C#

I will get 3mins of delay at the start of the below program.but where as in hyper terminal it shows every data for every 2 secs.
Her is my below code.please let me know where i went wrong .How i can rectify this delay. any suggestion?
private void StartReceiving()
{
// coding part of receiving changed.
try
{
string IPStr = textBox1_IPaddress.Text.Trim();
string portStr = textBox2_Port.Text.Trim();
int port = Convert.ToInt32(portStr);
int bytesRead = 0;
byte[] buffer = new byte[9];
//------------------------------------------------------------------
IPAddress ipAddress = System.Net.IPAddress.Parse(IPStr);
//create server's tcp listener for incoming connection
try
{
textBox3.Visible = true;
client = new TcpClient();
client.Connect(IPStr, port);
ns = client.GetStream();
while (true)
{
if (ns.DataAvailable)
{
byte[] data = ReadNumberBytes(ns, 9);
ASCIIEncoding encoder = new ASCIIEncoding();
msg = encoder.GetString(data);
textBox3.AppendText(msg);
textBox3.AppendText("\n");
GetData(msg);
}
else
{
Thread.Sleep(4000);
byte[] data = ReadNumberBytes(ns, 9);
ASCIIEncoding encoder = new ASCIIEncoding();
msg = encoder.GetString(data);
GetData(msg);
}
}
client.Close();
}
catch (SocketException se)
{
//message box;
}
}
}
public static byte[] ReadNumberBytes(NetworkStream stream, int n)
{
byte[] buffer = new byte[n];
int bytesRead = 0;
int chunk;
while (bytesRead < n)
{
chunk = stream.Read(buffer, (int)bytesRead, buffer.Length - int)bytesRead);
if (chunk == 0)
{
// error out.
throw new Exception("Unexpected disconnect");
}
bytesRead += chunk;
}
return buffer;
}

Categories