lose bytes Socket Programming - c#

i am developing application which send and receive data between two computers but there is problem which i am facing when i send data the file size would be 4.56 kb but when i receive data on other side the file size reduce to 1.42 kb and data write in file also in complete my receiving byte size is 1024 * 5000.i am using c#.i am using TCP
here is my code
i am first sending data to tell other computer what file i want to receive
private void GetLoginFile()
{
Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
char[] delimiter = splitter.ToCharArray();
byte[] fileName = Encoding.UTF8.GetBytes(myIP + "_GetLoginFile"); //file name
byte[] fileData;
fileData = Encoding.UTF8.GetBytes("null");
//byte[] fileData = reads.ReadToEnd().to; //file
byte[] fileNameLen = BitConverter.GetBytes(fileName.Length); //lenght of file name
clientData = new byte[4 + fileName.Length + fileData.Length];
fileNameLen.CopyTo(clientData, 0);
fileName.CopyTo(clientData, 4);
fileData.CopyTo(clientData, 4 + fileName.Length);
System.Net.IPAddress ipAdd = System.Net.IPAddress.Parse(serverIP);
IPEndPoint ipEnd = new IPEndPoint(ipAdd, 9050);
clientSock.Connect(ipEnd); //target machine's ip address and the port number
clientSock.Send(clientData);
byte[] clientData1 = new byte[1024 * 5000];
string receivedPath = mypath + "XML\\";
int receivedBytesLen = clientSock.Receive(clientData1);
int fileNameLen1 = BitConverter.ToInt32(clientData1, 0);
string fileName1 = Encoding.ASCII.GetString(clientData1, 4, fileNameLen1);
//string file = Encoding.UTF8.GetString();
BinaryWriter bWrite = new BinaryWriter(File.Open(receivedPath + fileName1, FileMode.Append));
bWrite.Write(clientData1, 4 + fileNameLen1, receivedBytesLen - 4 - fileNameLen1);
//clientSock.Shutdown(SocketShutdown.Send);
bWrite.Close();
clientSock.Close();
}
catch (Exception ex)
{
clientSock.Close();
MessageBox.Show(ex.Message);
}
}
can anyone help me out to solve this problem.

Well, you haven't given any code... but I suspect it's your receiving code which is wrong.
You should be looping round, reading until a Read call on the stream returns 0. Don't assume you'll get all the data in one call.
EDIT: Yup, look at your receiving code:
int receivedBytesLen = clientSock.Receive(clientData1);
What makes you think you've received all the data you need in that one call? You need to loop round, receiving until either the other end closes the connection, or you've read all the data you need.

Are you using UDP sockets? If so, then everything is fine: udp is not reliable. Use TCP to get every single byte sent.

Related

TcpListener is not receiving any data

i have an issue where im not receiving any bytes from the connected TcpClient!
Server: (i attempt to add the received message into a listbox, but nothing comes out.
//tl is a TcpListener
//I set this up in a 500 milisecond loop. No worries about that.
if (tl.Pending())
{
TcpClient tcp = tl.AcceptTcpClient();
var s = tcp.GetStream();
int bytesRead = s.Read(new byte[tcp.ReceiveBufferSize], 0,
tcp.ReceiveBufferSize);
string dataReceived = Encoding.ASCII.GetString(new
byte[tcp.ReceiveBufferSize], 0, bytesRead);
listBox1.Items.Add(dataReceived);
tcp.Close();
oac++; //Overall connection count
label3.Text = "Overall Connections: " + oac; //logging connections
}
Client:
void Send(){
TcpClient c = new TcpClient(Im not including my ip., 4444);
System.IO.StreamWriter w = new System.IO.StreamWriter(c.GetStream());
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes($"Username: \"
{textBox1.Text}\" | Password: \"{textBox2.Text}\"");
NetworkStream nwStream = c.GetStream();
nwStream.Write(bytesToSend, 0, bytesToSend.Length);
nwStream.Flush();
}
I The connection works, but theres some issues receiving data. it just comes out blank
On serverside, your problem is that you renew toy byte array new byte[tcp.ReceiveBufferSize]. You could also do something like this:
using( var inputStream = new MemoryStream() )
{
tcp.GetStream().CopyTo(inputStream);
Encoding.ASCII.GetString(inputStream.ToArray());
listBox1.Items.Add(dataReceived);
...
}
Remember using on all IDisposable's, else you will run out of resources.

C# Socket connection doesn't work

I'm Trying to create a code to send a TCP message to a server.
When I use AutoIT Script Language with this code:
Example()
Func Example()
Local $ConnectedSocket, $szData
Local $szIPADDRESS = "10.200.0.104"
Local $nPORT = 1040
; Start The TCP Services
TCPStartup()
; Initialize a variable to represent a connection
$ConnectedSocket = -1
;Attempt to connect to SERVER at its IP and PORT 1040
$ConnectedSocket = TCPConnect($szIPADDRESS, $nPORT)
; If there is an error... show it
If #error Then
MsgBox(4112, "Error", "TCPConnect failed with WSA error: " & #error)
Else
$szData="0x0021601FA10706052B0C00815ABE14281206072B0C00821D8148A007A0050303000800000DA20B0201013006020200D30500"
TCPSend($ConnectedSocket, $szData)
EndIf
EndFunc;==>Example
Works fine but I need to write the same code in C#. I try to do this:
private static byte[] MessageToByteArray(string message, Encoding encoding)
{
var byteCount = encoding.GetByteCount(message);
if (byteCount > byte.MaxValue)
throw new ArgumentException("Message size is greater than 255 bytes in the provided encoding");
var byteArray = new byte[byteCount + 1];
byteArray[0] = (byte)byteCount;
encoding.GetBytes(message, 0, message.Length, byteArray, 1);
return byteArray;
}
public static void Main(string[] args)
{
const string message = "0x0021601FA10706052B0C00815ABE14281206072B0C00821D8148A007A0050303000800000DA20B0201013006020200D30500";
var byteArray = MessageToByteArray(message, Encoding.ASCII);
Socket m_socClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
System.Net.IPAddress ipAdd = System.Net.IPAddress.Parse("10.200.0.104");
System.Net.IPEndPoint remoteEP = new IPEndPoint(ipAdd, 1040);
m_socClient.Connect(remoteEP);
try
{
m_socClient.Send(byteArray);
}
catch (SocketException se)
{
Console.WriteLine(se.Message.ToString());
}
}
But this code doesn't work. The server shows when he receives the command. With C# code, the server shows that have connected but the command doesn't execute.
Are you sure you have to prefix the length?
byteArray[0] = (byte)byteCount;
encoding.GetBytes(message, 0, message.Length, byteArray, 1);
Often you have a null-terminated string:
encoding.GetBytes(message, 0, message.Length, byteArray, 0);
byteArray[byteArray.Length - 1] = (byte)'\0';

Receive a file from a client and saving to a file in server in C#

What I want to do is to receive the file send from the client. But at the problem line shown below I get an exception
System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Users\asd\Desktop\'.
This is my server code:
IPEndPoint ipEnd;
Socket sock;
byte[] clientData = new byte[1024 * 5000];
ipEnd = new IPEndPoint(IPAddress.Any, 5000);
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
sock.Bind(ipEnd);
sock.Listen(5000);
Socket clientSock=sock.Accept();
int receivedBytesLen = clientSock.Receive(clientData);
int fileNameLen = BitConverter.ToInt32(clientData, 0);
string fileName = Encoding.ASCII.GetString(clientData, 4, fileNameLen);
BinaryWriter bWrite = new BinaryWriter(File.Open(#"C:\Users\asd\Desktop\"+ fileName,FileMode.Append));//problem Line
bWrite.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 - fileNameLen);
bWrite.Close();
clientSock.Close();
MessageBox.Show("recieved...");
I would not have your code save to the desktop you could be having permissions issues if your code is running as a different user than the desktop you specified. Change your code to the following and see if this fixes your problem
string destFolder = #"C:\ReceivedFiles"
if (Directory.Exists(destFolder) == false)
Directory.CreateDirectory(destFolder);
BinaryWriter bWrite = new BinaryWriter(File.Open(Path.Combine(destFolder, FileName), FileMode.Append));
On to other problems with your code:
int receivedBytesLen = clientSock.Receive(clientData);
First of all, this does not guarantee that you got all of the data. If the payload is bigger than one datagram you will need to call Receive multiple times. The only way to know how many times you need to call is you need to somehow send the length of the entire binary before hand or close the connection after the file is done client side and loop building a buffer (or writing it out as it comes in) until Receive returns 0.
Secondly, you should also be using using to make sure your classes get disposed properly in the event of a exception
using(Socket clientSock=sock.Accept())
{
//This needs to be redone, see my first point
int receivedBytesLen = clientSock.Receive(clientData);
int fileNameLen = BitConverter.ToInt32(clientData, 0);
string fileName = Encoding.ASCII.GetString(clientData, 4, fileNameLen);
using(BinaryWriter bWrite = new BinaryWriter(File.Open(#"C:\Users\asd\Desktop\"+ fileName,FileMode.Append)))
{
bWrite.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 - fileNameLen);
}
}

Server does not get the message of client

I successfully made a WebSocket server in C# which I can connect to. I make the handshake as RFC 6455 requires it.
Whatever I send (via WebSocket.send()) to it (for example "asd") the stream only has 9 bytes of data which is "unrepresentable" by UTF8.
using System.Net.Sockets;
using System.Net;
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
class Server
{
public static void Main()
{
TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 80);
server.Start();
TcpClient client = server.AcceptTcpClient();
NetworkStream stream = client.GetStream();
Boolean isHandshaked = false;
while (true)
{
while (!stream.DataAvailable)
{
}
Byte[] bytes = new Byte[client.Available];
stream.Read(bytes, 0, bytes.Length);
if (!isHandshaked)
{
Byte[] response = Encoding.UTF8.GetBytes("HTTP/1.1 101 Switching Protocols" + Environment.NewLine
+ "Connection: Upgrade" + Environment.NewLine
+ "Upgrade: websocket" + Environment.NewLine
+ "Sec-WebSocket-Accept: " + Convert.ToBase64String(
SHA1.Create().ComputeHash(
Encoding.UTF8.GetBytes(
new Regex("Sec-WebSocket-Key: (.*)").Match(
Encoding.UTF8.GetString(bytes)
).Groups[1].Value.Trim() + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
)
)
) + Environment.NewLine
+ Environment.NewLine);
stream.Write(response, 0, response.Length);
isHandshaked = true;
}
else
{
Console.WriteLine(Encoding.UTF8.GetString(bytes));
}
}
}
}
Where I missed something?
Messages between client and server are not sent as plain text. See the data framing section of the standard for how to encode/decode them.
For your example of a client sending a 3 byte string, this will result in a message of
1 byte - 0x81 - saying that this is a non-fragmented text message
1 byte - 0x83 - saying that the message body is 3 bytes long and it's contents are masked (all client -> server messages use masking. server -> client messages must not be masked). The top bit (byte_val & 0x80) is set if a message is masked. The remaining 7 bits (byte_val & 0x7F) gives the length of the messages up to 125 bytes. See link below for how to determine the length of longer messages.
4 bytes - mask. Always 4 bytes. Content determined by the client and should change for each message
3 bytes - message. Can be decoded using the mask and algorithm in section 5.3 of the spec.
You can unmask a message using code like the following
byte mask[4];
byte[] msg_data;
// read message, initialising mask, msg_data
for (int i=0; i<msg_data.Length; i++)
{
msg_data[i] = msg_data[i] ^ mask[i%4]
}
If you need more detail, this previous post explains message sending/receiving and includes some helpful pseudo code.
Having an empty loop to check for data i.e. while (!stream.DataAvailable){} is really a bad practice that you can avoid.
The read method is a blocking method, so it will wait until the data is available
int bufferSize = 1024; // change it as you want
byte[] message = new byte[bufferSize];
readLength = stream.Read(message, 0, bufferSize);
You can try code below and see if it works, i suspect you are not reading full response.
byte[] buffer = new byte[4155];
int bytesRead = 0;
using (var input = client.GetStream())
{
while (true)
{
bytesRead = input.Read(buffer, 0, buffer.Length);
totalBytes += bytesRead;
if (bytesRead > 0)
// keep processing ur data here, add it to another buffer maybe
else
break; // come out of while loop if there is no data
}
}
}

Index and count must refer to a location within the buffer. Parameter name: bytes

Hello guys im getting This error please see the attachment >> Index and count must refer to a location within the buffer. Parameter name: bytes
When im using debugger i dont get this error and everything goes fine i cannot understand what this error is
this is my server code :
IPEndPoint ipEnd = new IPEndPoint(IPAddress.Any, 27015);
Socket sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
sck.Bind(ipEnd);
sck.Listen(100);
Socket clientSocket = sck.Accept();
string[] fNames = new string[3];
fNames[0] = "01.jpg";
fNames[1] = "02.jpg";
fNames[2] = "03.jpg";
string filePath = "D:\\";
byte[] FilesCount = BitConverter.GetBytes(fNames.Count());
clientSocket.Send(FilesCount);
for (int i = 0; i < fNames.Count(); i++)
{
byte[] fileNameByte = Encoding.ASCII.GetBytes(fNames[i]);
byte[] fileData = File.ReadAllBytes(filePath + fNames[i]);
byte[] clientData = new byte[4 + fileNameByte.Length + fileData.Length];
byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);
fileNameLen.CopyTo(clientData, 0);
fileNameByte.CopyTo(clientData, 4);
fileData.CopyTo(clientData, 4 + fileNameByte.Length);
clientSocket.Send(clientData);
}
clientSocket.Close();
And Client:
Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
clientSock.Connect(IPAddress.Parse("46.49.70.30"), 27015);
byte[] clientData = new byte[1024 * bt];
string receivedPath = "D:/df/";
byte[] FileQuantityByte = new byte[1024];
clientSock.Receive(FileQuantityByte);
int FileQuantity = BitConverter.ToInt32(FileQuantityByte, 0);
for (int i = 0; i < FileQuantity; i++)
{
int receivedBytesLen = clientSock.Receive(clientData);
int fileNameLen = BitConverter.ToInt32(clientData, 0);
string fileName = Encoding.ASCII.GetString(clientData, 4, fileNameLen);
//Console.WriteLine("Client:{0} connected & File {1} started received.", clientSock.RemoteEndPoint, fileName);
BinaryWriter bWrite = new BinaryWriter(File.Open(receivedPath + fileName, FileMode.Append));
bWrite.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 - fileNameLen);
//Console.WriteLine("File: {0} received & saved at path: {1}", fileName, receivedPath);
bWrite.Close();
}
clientSock.Close();
EDIT : http://imageshack.us/f/202/errbk.jpg/
The exception is telling exactly what the problem is: one of your parameters isn't what you think it should be.
What is the length of clientData? What is the value of fileNameLen when you call Encoding.ASCII.GetString? What is the value of bt, which is used to initialize your clientData array?
If this doesn't happen in the debugger, then add some code to output the values of clientData and fileNameLen before the call.
One problem is that clientSock.Receive might not get all of the data at once. If you're sending an especially large file, it's possible that clientSock.Receive will return without reading everything. As documentation for Socket.Receive says:
If you are using a connection-oriented Socket, the Receive method will read as much data as is available, up to the size of the buffer.
It's possible that not all of the data is available yet, or that the buffer is smaller than the file size. To ensure that you get all of the data, you have to do this:
int totalBytesRead = 0;
int bytesRead = 0;
while ((bytesRead = clientSock.Receive(clientData, totalBytesRead,
clientData.Length - totalBytesRead, SocketFlags.None)) != 0)
{
totalBytesRead += bytesRead;
}
Receive will return 0 when there is no more data available. Only then can you be sure that you've received all of the data.
Solution is simple.
I've got similar problem on Encoding.UTF8.GetString(array[byte], index, array[byte].Length).
Problem is that method will TAKE some count of bytes FROM some position in your array, so you must take not array[byte].Length, but less than array[byte].Length - index.
If your array has 10 elements and you want to take all from 5th position, you can't take 10 elements.
So, again — Encoding.UTF8.GetString(array[byte], FROM, TAKE)

Categories