data received different from data sent through a c sharp socket - c#

I'm trying to send a file from a client to a server, so I load the file in a byte array in the client side, and send it to the server through the send() method, but the received array is different and bigger than the array sent, I wonder if it's a protocol problem (but I'm using tcp protocol wich assure error detection ):
Client code:
IPAddress ipAddress = new IPAddress(ip);
IPEndPoint ipEnd = new IPEndPoint(ipAddress, 5656);
Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
FileStream fl = File.Open("pos.xls",FileMode.Open);
byte[] fileData = ReadFully(fl);
fl.Close();
byte[] clientData = new byte[ fileData.Length];
fileData.CopyTo(clientData,0);
curMsg = "Connection to server ...";
clientSock.Connect(ipEnd);
curMsg = "File sending...";
clientSock.Send(clientData);
curMsg = "Disconnecting...";
clientSock.Close();
curMsg = "File transferred.";
Server code:
curMsg = "Starting...";
sock.Listen(100);
curMsg = "Running and waiting to receive file.";
byte[] clientData = new byte[1024 * 5000];
while (true)
{
Socket clientSock = sock.Accept();
clientData = new byte[1024 * 5000];
int receivedBytesLen = clientSock.Receive(clientData);
curMsg = "Receiving data...";
FileStream fz = writeFully(clientData);
fz.Close();
curMsg = "Saving file...";

You have defined clientData = new byte[1024 * 5000]; - and you then don't use receivedBytesLen. I can't remember whether that Receive overload will read as much as it can until EOF, or simply "some or EOF" (the latter being the Stream.Read behavior), but you must verify and use receivedBytesLen.
IMO, the approach of a fixed buffer is inherently flawed, as it doesn't cope well with oversized inputs either. Personally I would use a NetworkStream here; then your entire code becomes:
using(var fz = File.Create(path)) {
networkStream.CopyTo(fz);
}
Another common approach here is to send the expected size as a prefix to the data; that way you can verify that you have the data you need. I personally wouldn't use this information to create a correct-sized buffer in memory though, as that still doesn't allow for epic-sized files (a Stream, however, does).

Related

unable to receive full file in tcp client server

Here is my server code for reading a mp4 file and sending to the client
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp);
IPEndPoint ep = new IPEndPoint(IPAddress.Any, 3400);
sock.Bind(ep);
sock.Listen(10);
sock = sock.Accept();
FileStream fs = new FileStream(#"E:\Entertainment\Songs\Video song\song.mp4",FileMode.Open);
BinaryReader br = new BinaryReader(fs);
byte[] data = new byte[fs.Length];
br.Read(data, 0, data.Length);
sock.Send(data);
fs.Close();
sock.Close();
Here is the client code
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3400);
sock.Connect(ep);
MemoryStream ms = new MemoryStream();
int size = 3190551; // I know the file size is about 30 mb
int rec;
while (size > 0)
{
byte[] buffer;
if (size < sock.ReceiveBufferSize)
{
buffer = new byte[size];
}
else
{
buffer = new byte[sock.ReceiveBufferSize];
}
rec = sock.Receive(buffer, 0, buffer.Length, 0);
size = size - rec;
ms.Write(buffer, 0, buffer.Length);
}
byte[] data = ms.ToArray();
FileStream fs = new FileStream("E:/song.mp4",FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs)
bw.Write(data);
fs.Close();
sock.Close();
**At the end i just get the data in between 3 to 4 mb.... im new to socket programming and I don't know where the problem is... whether its sending side or receiving !!!! it looks like I just receive a single chunk of data from the server side **
I think the problem is here
int size = 3190551; // I know the file size is about 30 mb
you are reading just 3190551 byte which is 3.04mb not 30mb.
try to send length of your file at the beginning of your message so client will know how many bytes it should get from server.

Easy way to send multiple images in a single byte array (via TCP) C#?

Here's the problem: I've successfully setup an app that will pull individual frames of video from a phone and move them to the server. But as you know, the inherent latency won't allow for a smooth transition on the server side. I'm guessing I need to package a number of images in a single byte array and unpack them on the server side. But is there a clean/simple way to do this? Could I use a multi-dimensional array? Something else?
Here's what I got client side (payload is an incoming image converted to a single byte array):
if (_socket != null)
{
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
socketEventArg.RemoteEndPoint = _socket.RemoteEndPoint;
socketEventArg.UserToken = null;
socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
{
response = e.SocketError.ToString();
// Unblock the UI thread
_clientDone.Set();
});
socketEventArg.SetBuffer(payload, 0, payload.Length);
_clientDone.Reset();
_socket.SendAsync(socketEventArg);
_clientDone.WaitOne(TIMEOUT_MILLISECONDS);
}
And here's what I'm doing on the server side:
const int portNo = portNumber;
TcpListener listener = new TcpListener(portNo);
listener.Start();
Console.WriteLine("Listening...");
TcpClient tcpClient = listener.AcceptTcpClient();
NetworkStream NWStream = tcpClient.GetStream();
byte[] bytesToRead = new byte[tcpClient.ReceiveBufferSize + 1];
FrameCount += 1;
int numBytesRead = NWStream.Read(bytesToRead, 0, Convert.ToInt32(tcpClient.ReceiveBufferSize));
string FILE_NAME = "c:\\frames\\" + FrameCount.ToString() + ".gif";
System.IO.FileStream fs = null;
fs = new FileStream(FILE_NAME, FileMode.CreateNew, FileAccess.Write);
fs.Write(bytesToRead, 0, numBytesRead);
fs.Close();
tcpClient.Close();
listener.Stop();
StartImage();
As long as your images are larger than the tcp package size (I think it's 1024 by default on Windows) you won't get performance from sending multiple images in one Send/Receive.
However, sending multiple images per socket connection is useful because you will avoid the overhead of multiple connection handshakes.
Before you optimize your packages, try to send multiple images one after another on the same socket connection.

Need help on bytes via Socket

I'm trying to send a couple of data via Sockets, so it's converted to bytes and then back to String on the Server. But I can only do one apparently.
Server code:
static void Read(IAsyncResult ar)
{
int fileNameLen = 1;
//int userNameLen = 9;
State newState = (State)ar.AsyncState; //gets state of Socket
Socket handler = newState.Socket_w; //passes Socket to handler
int bytesRead = handler.EndReceive(ar); //terminates Data Receive from Socket.
if (bytesRead > 0)
{
if (flag == 0)
{
fileNameLen = BitConverter.ToInt32(newState.buffer, 0); //gets filename length
fileName = Encoding.UTF8.GetString(newState.buffer, 4, fileNameLen); //gets filename
//userNameLen = BitConverter.ToInt32(newState.buffer, 8);
//getUsername = Encoding.UTF8.GetString(newState.buffer, 8, fileNameLen);
flag++;
}
}
}
Client code:
internal static void uploadFile(string host, string username, string getGame, string filename, string filepath)
{
byte[] m_clientData;
Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
byte[] fileName = Encoding.UTF8.GetBytes(username + "_" + filename);
byte[] fileData = File.ReadAllBytes(filepath);
byte[] fileNameLen = BitConverter.GetBytes(fileName.Length);
//byte[] sendUsername = Encoding.UTF8.GetBytes(username);
//byte[] sendUsernameLen = BitConverter.GetBytes(sendUsername.Length);
//byte[] sendGame = Encoding.UTF8.GetBytes(getGame);
//byte[] sendGameLen = BitConverter.GetBytes(sendGame.Length);
m_clientData = new byte[4 + fileName.Length + fileData.Length];
fileNameLen.CopyTo(m_clientData, 0);
fileName.CopyTo(m_clientData, 4);
fileData.CopyTo(m_clientData, 4 + fileName.Length);
//sendUsernameLen.CopyTo(m_clientData, 0);
//sendUsername.CopyTo(m_clientData, 4);
//sendGameLen.CopyTo(m_clientData, 0);
//sendGame.CopyTo(m_clientData, 4);
clientSock.Connect(host, 8889);
clientSock.Send(m_clientData); //tofix exception
clientSock.Close();
}
I can't seem to decrypt it properly over on Server. Can anyone help me with the buffersizes and whatnot?
Read does not know anything about what was sent; TCP is basically just a stream - so there is absolutely nothing to say that you have all the data in one call to Read; you could have:
exactly the amount of data you sent
part of one message
17 messages
the end of one message and the start of the next
1 solitary byte from a message
You need to devise some kind of framing protocol that lets the receiver know when they have an entire message. That could be as simple as a length prefix, or can be more complex. You should then buffer the data in memory (or process it gradually) until you have the entire message. One call to Read is very unlikely to represent a single and complete message. Indeed, this is guaranteed not to be the case if a message is larger than your newstate.buffer, but you can get the same result even for small messages and a large buffer.

Send File From Java to C# using Socket

Can anyone give me a small tutorial on how to send file from java server to c# client and on receive complete acknowledgment message from c# to java. Actually I'm new to C# and dont know how to do socket programming. I'm stuck in it since long. Tried many codes. Some codes receive incomplete files some stuck in infinite loop. Please help me in this regard.
Thanks
EDIT
Here is what I have tried:
C# Server:
{
IPAddress ipAd = IPAddress.Parse("192.168.1.131");
// use local m/c IP address, and
// use the same in the client
/* Initializes the Listener */
TcpListener myList = new TcpListener(ipAd, 5600);
/* Start Listeneting at the specified port */
myList.Start();
Console.WriteLine("The server is running at port 5600...");
Console.WriteLine("The local End point is :" +
myList.LocalEndpoint);
Console.WriteLine("Waiting for a connection.....");
m:
clientSock = myList.AcceptSocket();
//clientSock.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReceiveTimeout,10000);
Console.WriteLine("Connection accepted from " + clientSock.RemoteEndPoint);
//byte[] b = new byte[100];
//int k = clientSock.Receive(b);
string fileName = "hello.wav";
NetworkStream networkStream = new NetworkStream(clientSock);
StreamReader sr = new StreamReader(networkStream);
//read file length
int length = int.Parse(sr.ReadLine());
if (networkStream.CanRead)
{
BinaryWriter bWrite = new BinaryWriter(File.Open(receivedPath + fileName, FileMode.Create));
int receivedBytesLen = -1;
byte[] clientData = new byte[4096 * 5000];
receivedBytesLen = networkStream.Read(clientData, 0, clientData.Length);
bWrite.Write(clientData, 0, receivedBytesLen);
do
{
receivedBytesLen = networkStream.Read(clientData, 0,clientData .Length);
bWrite.Write(clientData, 0, receivedBytesLen);
} while (receivedBytesLen > 0);
bWrite.Close();
networkStream.Close();
}
Console.WriteLine("Client:{0} connected & File {1} started received.", clientSock.RemoteEndPoint, fileName);
Console.WriteLine("File: {0} received & saved at path: {1}", fileName, receivedPath);
Recognizer_2 recognizeVoice = new Recognizer_2(clientSock);
recognizeVoice.recognize_wav(); // Acknowledgement
Console.WriteLine("\nResult Sent to the Client");
goto m;
}
Java Client:
Socket socket = new Socket("192.168.1.131", 5600);
BufferedReader response_Stream = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
File f = new File(mFileName);
byte[] buffer = new byte[(int) f.length()];
FileInputStream fis = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(buffer, 0, buffer.length);
OutputStream outputStream = socket.getOutputStream();
outputStream.write(buffer);
outputStream.flush();
String final_Result_String = "";
if (response_Stream != null) {
String respose_text = "";
while ((respose_text = response_Stream.readLine()) != null) {
final_Result_String += respose_text;
}
}
Toast.makeText(getApplicationContext(), final_Result_String, 1)
.show();
outputStream.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
There is no dependance between the languages used by the server or the client.
Just the structure of the data is important !
You should search for some tutorials on socket programming with C#.
For example: http://www.codeproject.com/Articles/10649/An-Introduction-to-Socket-Programming-in-NET-using
But the language doesn't matter, understand how the data is formatted when sent on the network.
Edit: you should add a byte or two in the data indicating the length of it. It's not because you dont have data to read once that all the data has been received.

TCP Client/Server Image Transfer

I'm trying to send an image using a TCP socket. The client connects to the server without any problems and start to receive the data. The problem is when I try to convert the stream to an image using FromStream() method, I get an OutOfMemory Exception. Can anyone help me out? Really important!! Here is the code;
client snippet
private void btnConnect_Click(object sender, EventArgs e)
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
TcpClient client = new TcpClient();
client.Connect(ipAddress, 9500);
NetworkStream nNetStream = client.GetStream();
while (client.Connected)
{
lblStatus.Text = "Connected...";
byte[] bytes = new byte[client.ReceiveBufferSize];
int i;
if (nNetStream.CanRead)
{
nNetStream.Read(bytes, 0, bytes.Length);
Image returnImage = Image.FromStream(nNetStream); //exception occurs here
pictureBox1.Image = returnImage;
}
else
{
client.Close();
nNetStream.Close();
}
}
client.Close();
}
server snippet
try
{
IPAddress ipAddress = Dns.Resolve("localhost").AddressList[0];
TcpListener server = new TcpListener(ipAddress, 9500);
server.Start();
Console.WriteLine("Waiting for client to connect...");
while (true)
{
if (server.Pending())
{
Bitmap tImage = new Bitmap(Image URL goes here);
byte[] bStream = ImageToByte(tImage);
while (true)
{
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected");
while (client.Connected)
{
NetworkStream nStream = client.GetStream();
nStream.Write(bStream, 0, bStream.Length);
}
}
}
}
}
catch (SocketException e1)
{
Console.WriteLine("SocketException: " + e1);
}
}
static byte[] ImageToByte(System.Drawing.Image iImage)
{
MemoryStream mMemoryStream = new MemoryStream();
iImage.Save(mMemoryStream, System.Drawing.Imaging.ImageFormat.Gif);
return mMemoryStream.ToArray();
}
Thanks a lot in advanced,
There are a couple of things wrong, including, possibly the protocol you are using. First, the client:
If you expect a single image, there is no need for the while loop
Your client first does a Read which reads some information from the server into the buffer, and then it calls Image.FromStream(nNetStream) which will read incomplete data.
Whenever you read from a stream, keep in mind that a single Read call is not guaranteed to fill your buffer. It can return any number of bytes between 0 and your buffer size. If it returns 0, it means there is no more to read. In your case this also means that your client currently has no way of knowing how much to read from the server. A solution here is to have the server send the length of the image as the first piece of information. Another solution would be to have the server disconnect the client after it has sent the information. This may be acceptable in your case, but it will not work if you need persistent connections (e.g. pooled connections on client side).
The client should look something like this (assuming the server will disconnect it after it sends the data):
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
using (TcpClient client = new TcpClient())
{
client.Connect(ipAddress, 9500);
lblStatus.Text = "Connected...";
NetworkStream nNetStream = client.GetStream();
Image returnImage = Image.FromStream(nNetStream);
pictureBox1.Image = returnImage;
}
Next, the server:
Instead of Pending, you can simply accept the client
The server sends the stream over and over again to the same client, until they disconnect. Instead, send it only once.
The server loop should look something like this:
Bitmap tImage = new Bitmap(Image URL goes here);
byte[] bStream = ImageToByte(tImage);
while (true)
{
// The 'using' here will call Dispose on the client after data is sent.
// This will disconnect the client
using (TcpClient client = server.AcceptTcpClient())
{
Console.WriteLine("Connected");
NetworkStream nStream = client.GetStream();
try
{
nStream.Write(bStream, 0, bStream.Length);
}
catch (SocketException e1)
{
Console.WriteLine("SocketException: " + e1);
}
}
}
This part looks funky to me:
byte[] bytes = new byte[client.ReceiveBufferSize];
int i;
if (nNetStream.CanRead)
{
nNetStream.Read(bytes, 0, bytes.Length);
Image returnImage = Image.FromStream(nNetStream); //exception occurs here
First you read client.ReceiveBufferSize bytes into the "bytes" array, and then you proceed to construct the image from what's left on the stream. What about the bytes you just read into "bytes"?
I recomend you to use this code(I've created it by myself and tested it and it works perfect.):
public void Bitmap ConvertByteArrayToBitmap(byte[] receivedBytes)
{
MemoryStream ms = new MemoryStream(receivedBytes);
return new Bitmap(ms, System.Drawing.Imaging.ImageFormat.Png); // I recomend you to use png format
}
Use this to convert received byteArray to an image.
It seems like your server is sending the image over and over again:
while (client.Connected)
{
NetworkStream nStream = client.GetStream();
nStream.Write(bStream, 0, bStream.Length);
}
If the server can send data fast enough, the client will probably keep receiving it.
Here's a solution :
Server side :
tImage.Save(new NetworkStream(client), System.Drawing.Imaging.ImageFormat.Png);
Cliend side:
byte[] b = new byte[data.ReceiveBufferSize];
client.Receive(b);
MemoryStream ms = new MemoryStream(b);
Image receivedImag = Image.FromStream(ms);
or :
Image receivedImag = Image.FromStream(new NetworkStream(client));

Categories

Resources