1
I’m facing a problem.
I have the server code done in C++, running in Ubuntu.
And I have the client code done in C#, running in windows.
In the server code (C++) I came across a problem
//recebe tamanho arquivo
read(idSockfd, tmpBuffer, BUFSIZ_SOCKET);
int file_size = atoi(tmpBuffer);
bzero(tmpBuffer,BUFSIZ_SOCKET);
//recebe outra instrucao
read(idSockfd, tmpBuffer, BUFSIZ_SOCKET);
This worked when I sent the request from my computer (Windows 10), but on other computers like Windows 7 or "second" read
, like he sent something through the buffer.
To solve this problem, after a search I found the following solution:
Passing the parameter MSG_WAITALL
, this solved the problem. On all tested computers it worked..
recv(idSockfd, tmpBuffer, BUFSIZ_SOCKET, MSG_WAITALL);
However I have a function that receives files
FILE* received_file = fopen(fileName.c_str(), "w");
if (received_file == NULL)
{
printf("Erro ao receber o arquivo\n");
}
bzero(tmpBuffer,BUFSIZ_SOCKET);
int remain_data = file_size;
int len;
while (((len = recv(idSockfd, tmpBuffer, BUFSIZ_SOCKET, MSG_WAITALL)) > 0) && (remain_data > 0))
{
fwrite(tmpBuffer, sizeof(char), len, received_file);
remain_data -= len;
fprintf(stdout, "Recebendo %d bytes e falta:- %d bytes\n", len, remain_data);
}
printf("Fechando arquivo\n");
fclose(received_file);
It turns out that the "last" part of the file, will always be smaller than the buffer size, and with the instruction MSG_WAITWALL, is waiting for the whole buffer, and never gets the last bytes of the file.
I tried to change to the following way too
(((len = recv(idSockfd, tmpBuffer, BUFSIZ_SOCKET, 0)) > 0) && (remain_data > 0))
(((len = recv(idSockfd, tmpBuffer, BUFSIZ_SOCKET, 0)) > MSG_TRUNC) && (remain_data > 0))
(((len = recv(idSockfd, tmpBuffer, BUFSIZ_SOCKET, 0)) > MSG_PEEK) && (remain_data > 0))
(((len = recv(idSockfd, tmpBuffer, BUFSIZ_SOCKET, 0)) > MSG_PEEK | MSG_TRUNC) && (remain_data > 0))
but all my attempts were thwarted.
Follow the C# code that sends the file..
Socket s = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
s.Connect(conn.Ip, conn.Port);
buffer = new byte[102400];
//envia o lenght
byData = System.Text.Encoding.ASCII.GetBytes(new FileInfo(f.FileName).Length.ToString());
byData.CopyTo(buffer, 0);
debug = s.Send(buffer);
//envia o caminho
byData = System.Text.Encoding.ASCII.GetBytes(path);
byData.CopyTo(buffer, 0);
debug = s.Send(buffer);
//envia o arquivo
s.SendFile(f.FileName);
How can I have a guarantee of what receives is what the client application sent and not some "dirt", I say "dirt" because on computers tested with windows 7, receives a few bytes that honestly do not know where it came from.
Thanks for your attention and help.
Is this processing synchronous? Instead of MSG_WAITALL, you could use a monitor or semaphore for thread control?
– Erick Gallani
Originally is a
thread
, but I did tests on the main function, and the same problem happens..– Marco Giovanni
I found your description of the problem a little confusing...see if the answer I gave to this question help...what I can say is that I never had to use this flag MSG_WAITALL, and this flag will actually cause the problem that you reported last, that the application is stuck waiting to receive all the BUFSIZ_SOCKET bytes
– zentrunix
@Joséx. Thank you for your reply.. I will test, but probably this is what was happening, as you wrote in the reply 300 bytes can reach in 3 parts of 100 bytes. Thank you.
– Marco Giovanni
The correct one would be to have a file waiting state and another acquiring the file for example. Give read in 1 byte until you have been able to read 4 bytes. With these 4 bytes, you have the file size. Read 1 to 1 just like you did with the size and concatenating the buffer. At least this way I never had package problems in half or something as reported
– Kevin Kouketsu