send() shall return the number of bytes sent or error code, but all examples that I found check it only with error codes, but not with the number of bytes sent.
//typical example
int cnt=send(s,query,strlen(query),0);
if (cnt < 0) return(NULL);
//Hey, what about cnt < strlen(query)?
Q: Does "send()" always return the whole buffer?
A: No, not necessarily.
From Beej's Guide:
* http://beej.us/guide/bgnet/html/multi/syscalls.html#sendrecv
send() returns the number of bytes actually sent out—this might be
less than the number you told it to send! See, sometimes you tell it
to send a whole gob of data and it just can't handle it. It'll fire
off as much of the data as it can, and trust you to send the rest
later. Remember, if the value returned by send() doesn't match the
value in len, it's up to you to send the rest of the string. The good
news is this: if the packet is small (less than 1K or so) it will
probably manage to send the whole thing all in one go. Again, -1 is
returned on error, and errno is set to the error number.
Q: Does "recv()" always read the whole buffer?
A: No, absolutely not. You should never assume the buffer you've received is "the whole message". Or assume the message you receive is from one, single message.
Here's a good, short explanation. It's for Microsoft/C#, but it's applicable to all sockets I/O, in any language:
http://blogs.msdn.com/b/joncole/archive/2006/03/20/simple-message-framing-sample-for-tcp-socket.aspx
The answer is in another section of man 2 send:
When the message does not fit into the send buffer of the socket,
send() normally blocks, unless the socket has been placed in nonblock‐
ing I/O mode. In nonblocking mode it would fail with the error EAGAIN
or EWOULDBLOCK in this case. The select(2) call may be used to deter‐
mine when it is possible to send more data.
Or, alternatively, the POSIX version (man 3p send):
If space is not available at the sending socket to hold the message to
be transmitted, and the socket file descriptor does not have O_NONBLOCK
set, send() shall block until space is available. If space is not
available at the sending socket to hold the message to be transmitted,
and the socket file descriptor does have O_NONBLOCK set, send() shall
fail. The select() and poll() functions can be used to determine when
it is possible to send more data.
So, while a read of partial data is common, a partial send in blocking mode should not happen (barring implementation details).
Nope, it doesn't.
For reference, see the man page for send:
When the message does not fit into the send buffer of the socket, send()
normally blocks, unless the socket has been placed in nonblocking I/O mode.
In nonblocking mode it would fail with the error EAGAIN or EWOULDBLOCK in this
case. The select(2) call may be used to determine when it is possible to send
more data.
I've read through this question and other two related questions:
When a non-blocking send() only transfers partial data, can we assume it would return EWOULDBLOCK the next call?
Blocking sockets: when, exactly, does "send()" return?
I found not all answers reach an consensus and one or two answers have oppsite conclusion.
So I spent quite some time searching in book and playing with this code of #Damon that he posted in the comment of https://stackoverflow.com/a/19400029/5983841 .
I think most answers are wrong and my conlusion is:
A call to send has these possible outcomes:
There is at least one byte available in the send buffer:
1.1 → if send is blocking (the fd is not set as non-blocking and MSG_DONTWAIT is not specified in send), send blocks until there's enough room for the whole buffer to fit, and send the whole buffer.
1.2 → if send is non-blocking (fd set as non-blocking or MSG_DONTWAIT is specified in send), send returns the number of bytes accepted (possibly fewer than you asked for).
The send buffer is completely full at the time you call send.
→ if the socket is blocking, send blocks
→ if the socket is non-blocking, send fails with EWOULDBLOCK/EAGAIN
An error occurred (e.g. user pulled network cable, connection reset by peer) →send fails with another error
#1.1 conforms to man 2 send:
When the message does not fit into the send buffer of the socket, send() normally blocks, unless the socket has been placed in nonblocking I/O mode.
partial recv is easy to understand, while for partial send (from The Linux Programming Interface):
61.1 Partial Reads and Writes on Stream Sockets
...
A partial write may occur if there is insufficient buffer space to transfer all of the requested bytes and one of the following is true:
A signal handler interrupted the write() call (Section 21.5) after it transferred some of the requested bytes.
The socket was operating in nonblocking mode (O_NONBLOCK), and it was possible to transfer only some of the requested bytes.
An asynchronous error occurred after only some of the requested bytes had
been transferred. By an asynchronous error, we mean an error that occurs asynchronously with respect to the application’s use of calls in the sockets API. An asynchronous error can arise, for example, because of a problem with a TCP connection, perhaps resulting from a crash by the peer application.
In all of the above cases, assuming that there was space to transfer at least 1 byte, the write() is successful, and returns the number of bytes that were transferred to the output buffer.
...
(The case of signal interruption doesn't happen in most of the time and I have difficulties writing to prove a partial write in this case. Hope someone could help)
What's not made clear enough of man 2 send :
When the message does not fit into the send buffer of the socket, send() normally blocks, unless the socket has been placed in nonblocking I/O mode.
In nonblocking mode it would fail with the error EAGAIN or EWOULDBLOCK in this case.
is that in nonblocking mode it would fail if the buffer is completely full. If there's 1 byte available in send buffer, it won't fail but instead returns the number of bytes that were sent, aka a partial send. (the author of the book is also the mantainer of linux manpage https://www.kernel.org/doc/man-pages/maintaining.html ).
Prove of code, written by #Damon. I modifed 3~5 lines, making the server doesn't consume any packets, so as to demonstrate.
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
int create_socket(bool server = false)
{
addrinfo hints = {};
addrinfo* servinfo;
int sockfd = -1;
int rv;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = server ? AI_PASSIVE : 0;
if ((rv = getaddrinfo(server ? 0 : "localhost", "12345", &hints, &servinfo)))
{
printf("getaddrinfo failed: %s\n", gai_strerror(rv));
exit(1);
}
for(auto p = servinfo; p; p = p->ai_next)
{
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
{
perror("socket");
continue;
}
if(server)
{
int yes = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1)
{
close(sockfd);
perror("bind");
continue;
}
}
else
{
if(connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
{
close(sockfd);
perror("connect");
continue;
}
else
puts("client: connected");
}
break;
}
freeaddrinfo(servinfo);
return sockfd;
}
void server()
{
int socket = create_socket(true);
if(listen(socket, 5) == -1)
{
perror("listen");
exit(1);
}
puts("server: listening");
int conn = -1;
sockaddr_storage addr;
unsigned int sizeof_addr = sizeof(addr);
for(;;)
{
if((conn = accept(socket, (sockaddr *) &addr, &sizeof_addr)) == -1)
{
perror("accept");
}
else
{
puts("server: accept");
if(!fork()) // actually not necessary, only got 1 client
{
close(socket);
// char *buf = new char[1024*1024];
// read(conn, buf, 1024*1024); // black hole
// server never reads
break;
}
}
}
}
void do_send(int socket, const char* buf, unsigned int size/*, bool nonblock = false */)
{
unsigned int sent = 0;
unsigned int count = 0;
while(sent < size)
{
int n = send(socket, &buf[sent], size - sent, 0);
// int n = send(socket, &buf[sent], size - sent, MSG_DONTWAIT);
if (n == -1)
{
if(errno == EAGAIN)
{
printf(".");
printf("\n");
}
else
{
perror("\nsend");
return;
}
}
else
{
sent += n;
printf(" --> sent a chunk of %u bytes (send no. %u, total sent = %u)\n", n, ++count, sent);
}
}
}
void client()
{
const unsigned int max_size = 64*1024*1024; // sending up to 64MiB in one call
sleep(1); // give server a second to start up
int socket = create_socket();
unsigned int send_buffer_size = 0;
unsigned int len = sizeof(send_buffer_size);
if(getsockopt(socket, SOL_SOCKET, SO_SNDBUF, &send_buffer_size, &len))
perror("getsockopt");
// Linux internally doubles the buffer size, and getsockopt reports the doubled size
printf("send buffer size = %u (doubled, actually %u)\n", send_buffer_size, send_buffer_size/2);
if(socket == -1)
{
puts("no good");
exit(1);
}
char *buf = new char[max_size]; // uninitialized contents, but who cares
for(unsigned int size = 65536; size <= max_size; size += 16384)
{
printf("attempting to send %u bytes\n", size);
do_send(socket, buf, size);
}
puts("all done");
delete buf;
}
int main()
{
setvbuf(stdout, NULL, _IONBF, 0);
if(fork() > 0) server(); else client();
return 0;
}
compile and run
g++ -g -Wall -o send-blocking-and-server-never-read code-of-damon.cpp
./send-blocking-and-server-never-read > log1.log 2>&1
log1.log content
server: listening
client: connectedserver: accept
send buffer size = 2626560 (doubled, actually 1313280)
attempting to send 65536 bytes
--> sent a chunk of 65536 bytes (send no. 1, total sent = 65536)
attempting to send 81920 bytes
--> sent a chunk of 81920 bytes (send no. 1, total sent = 81920)
attempting to send 98304 bytes
--> sent a chunk of 98304 bytes (send no. 1, total sent = 98304)
attempting to send 114688 bytes
--> sent a chunk of 114688 bytes (send no. 1, total sent = 114688)
attempting to send 131072 bytes
--> sent a chunk of 131072 bytes (send no. 1, total sent = 131072)
attempting to send 147456 bytes
--> sent a chunk of 147456 bytes (send no. 1, total sent = 147456)
attempting to send 163840 bytes
--> sent a chunk of 163840 bytes (send no. 1, total sent = 163840)
attempting to send 180224 bytes
--> sent a chunk of 180224 bytes (send no. 1, total sent = 180224)
attempting to send 196608 bytes
--> sent a chunk of 196608 bytes (send no. 1, total sent = 196608)
attempting to send 212992 bytes
--> sent a chunk of 212992 bytes (send no. 1, total sent = 212992)
attempting to send 229376 bytes
--> sent a chunk of 229376 bytes (send no. 1, total sent = 229376)
attempting to send 245760 bytes
--> sent a chunk of 245760 bytes (send no. 1, total sent = 245760)
attempting to send 262144 bytes
--> sent a chunk of 262144 bytes (send no. 1, total sent = 262144)
attempting to send 278528 bytes
--> sent a chunk of 278528 bytes (send no. 1, total sent = 278528)
attempting to send 294912 bytes
then comment int n = send(socket, &buf[sent], size - sent, 0); and uncomment int n = send(socket, &buf[sent], size - sent, MSG_DONTWAIT);
compile and run again
g++ -g -Wall -o send-nonblocking-and-server-never-read code-of-damon.cpp
./send-nonblocking-and-server-never-read > log2.log 2>&1
log2.log content
server: listening
server: accept
client: connected
send buffer size = 2626560 (doubled, actually 1313280)
attempting to send 65536 bytes
--> sent a chunk of 65536 bytes (send no. 1, total sent = 65536)
attempting to send 81920 bytes
--> sent a chunk of 81920 bytes (send no. 1, total sent = 81920)
attempting to send 98304 bytes
--> sent a chunk of 98304 bytes (send no. 1, total sent = 98304)
attempting to send 114688 bytes
--> sent a chunk of 114688 bytes (send no. 1, total sent = 114688)
attempting to send 131072 bytes
--> sent a chunk of 131072 bytes (send no. 1, total sent = 131072)
attempting to send 147456 bytes
--> sent a chunk of 147456 bytes (send no. 1, total sent = 147456)
attempting to send 163840 bytes
--> sent a chunk of 163840 bytes (send no. 1, total sent = 163840)
attempting to send 180224 bytes
--> sent a chunk of 180224 bytes (send no. 1, total sent = 180224)
attempting to send 196608 bytes
--> sent a chunk of 196608 bytes (send no. 1, total sent = 196608)
attempting to send 212992 bytes
--> sent a chunk of 212992 bytes (send no. 1, total sent = 212992)
attempting to send 229376 bytes
--> sent a chunk of 229376 bytes (send no. 1, total sent = 229376)
attempting to send 245760 bytes
--> sent a chunk of 245760 bytes (send no. 1, total sent = 245760)
attempting to send 262144 bytes
--> sent a chunk of 262144 bytes (send no. 1, total sent = 262144)
attempting to send 278528 bytes
--> sent a chunk of 278528 bytes (send no. 1, total sent = 278528)
attempting to send 294912 bytes
--> sent a chunk of 178145 bytes (send no. 1, total sent = 178145)
.
.
.
.
.
.
// endless .
Compare the last output of log1.log and log2.log and you can tell that a blocking send blocks when there's no enough buffer to fit all 294912 bytes while a non-blocking send performs a partial write. This conforms to conclusion #1.
Special thanks to #user207421's different opinion that leads me on more searching.
Related
I have 2 Ubuntu 14.04 PCs. One is used as a server and the other one is used as a client. The client setup a TCP connection to the server which sends some packets back. Here's the code on the server:
send(sd, pkt, pkt_len, MSG_NOSIGNAL);
The code on the client side is also very simple:
read(sd, buf, buf_size);
If the transmissions on the server is spaced out, I don't see any issue. However, if server is doing rapid transmissions, then thing looks ugly. Here's an example when the server is sending 8 packets back-to-back.
The server code shows the size of these 8 packets are: 752 (bytes), 713, 713, 713, 396, 398, 396, 396
tcpdump on the server captures 4 TX packets: 752 (bytes), 1398, 1398, 929
tcpdump on the client captures 3 RX packets: 752 (bytes), 2796, 929
The client code shows it receives only 2 packets with 3548 bytes and 929 bytes, respectively.
So you can see all the bytes sent by the server are received by the client. However, packets are combined at various points in the transmission path. I guess this is due to TSO, GSO, GRO, etc. However, shouldn't these optimizations re-assemble the packets back to the correct form when the packets are delivered to the receiving application?
How do I get around this issue?
TCP is carefully designed to not only permit but implement exactly what you're seeing. It is a byte-stream protocol. If you want messages you have to implement them yourself via a superimposed application protocol.
How do I get around this issue?
So you're using TCP (a byte-stream-oriented transport mechanism) but you'd like it to have message-oriented behavior. You can't change the way TCP works (it is, by design, allowed to transport bytes in whatever-sized groups it chooses to, as long as the bytes are all received and they are received in the same order). But you can add a layer on top of TCP to simulate packet-oriented behavior.
For example, say you wanted to simulate the transmission of a 1000-byte "packet". Your sending program could first send out a fixed-size (let's say, 4-byte) header that would tell the receiver how many bytes the "packet" will contain:
size_t myPacketSize = 1000; // or whatever the size of your packet is
uint32_t bePacketSize = htonl(myPacketSize); // convert native-endian to big-endian for cross-platform compatibility
if (send(sd, &bePacketSize, sizeof(bePacketSize), 0) != sizeof(bePacketSize))
{
perror("send(header)");
}
.... then right after that you'd send out the packet's payload data:
if (send(sd, packetDataPtr, myPacketSize, 0) != myPacketSize)
{
perror("send(body)");
}
The receiver would need to receive the header/size value, then allocate an array of that size and receive the payload data into it. Since this code has to handle the incoming data correctly no matter how many bytes are returned by each recv() call, it's a little more complex than the sending code:
void HandleReceivedPseudoPacket(const char * packetBytes, uint32_t packetSizeBytes)
{
// Your received-packet-handling code goes here
}
// Parses an incoming TCP stream of header+body data back into pseudo-packets for handling
void ReadPseudoPacketsFromTCPStreamForever(int sd)
{
uint32_t headerBuf; // we'll read each 4-byte header's bytes into here
uint32_t numValidHeaderBytes = 0; // how many bytes in (headerBuf) are currently valid
char * bodyBuf = NULL; // will be allocated as soon as we know how many bytes to allocate
uint32_t bodySize; // How many bytes (bodyBuf) points to
uint32_t numValidBodyBytes = 0; // how many bytes in (bodyBuf) are currently valid
while(1)
{
if (bodyBuf == NULL)
{
// We don't know the bodySize yet, so read in header bytes to find out
int32_t numBytesRead = recv(sd, ((char *)&headerBuf)+numValidHeaderBytes, sizeof(headerBuf)-numValidHeaderBytes, 0);
if (numBytesRead > 0)
{
numValidHeaderBytes += numBytesRead;
if (numValidHeaderBytes == sizeof(headerBuf))
{
// We've read the entire 4-byte header, so now we can allocate the body buffer
numValidBodyBytes = 0;
bodySize = ntohl(headerBuf); // convert from big-endian to the CPU's native-endian
bodyBuf = (char *) malloc(bodySize);
if (bodyBuf == NULL)
{
perror("malloc");
break;
}
}
}
else if (numBytesRead < 0)
{
perror("recv(header)");
break;
}
else
{
printf("TCP connection was closed while reading header bytes!\n");
break;
}
}
else
{
// If we got here, then we know the bodySize and now we need to read in the body bytes
int32_t numBytesRead = recv(sd, &bodyBuf[numValidBodyBytes], bodySize-numValidBodyBytes, 0);
if (numBytesRead > 0)
{
numValidBodyBytes += numBytesRead;
if (numValidBodyBytes == bodySize)
{
// At this point the pseudo-packet is fully received and ready to be handled
HandleReceivedPseudoPacket(bodyBuf, bodySize);
// Reset our state variables so we'll be ready to receive the next header
free(bodyBuf);
bodyBuf = NULL;
numValidHeaderBytes = 0;
}
}
else if (numBytesRead < 0)
{
perror("recv(body)");
break;
}
else
{
printf("TCP connection was closed while reading body bytes!\n");
break;
}
}
}
// Avoid memory leak if we exited the while loop in the middle of reading a psuedo-packet's body
if (bodyBuf) free(bodyBuf);
}
Socket Used : udp
I have a client who sends 5000 bytes and a server with this code :
Client code :
cod = sendto (sFd, (void *) buffer, 5000, 0, (struct sockaddr *)
&soc, sizeof (struct sockaddr_in));
Server code :
//leghtBuffer = 5000
while (lenghtBuffer > 0 )
{
//I will insert a signal if pass more than 30 s ...
cod = recvfrom (sFd, buffer,256 , 0, (struct sockaddr *) &clientSoc, &lungimeSocket);
printf("Am received %d bytes " ,cod );
lenghtBuffer = lenghtBuffer - cod;
}
How can I read more than 1 time 256 bytes from this while (still using Udp socket)?
UDP is a message (datagram) based transport protocol and not stream based like TCP. Each sendto/recvfrom works in terms of complete messages.
On the sending end, each call to sendto() creates a datagram of the specified size and data, which in your case is 5000 bytes.
On the receiving end, each call to recvfrom() copies the next message in the receive buffer. Since your datagrams are 5000 bytes, but you're only providing a 256 byte buffer, your datagram is being truncated to 256 bytes as it's copied.
The recvfrom() OpenGroup specification clarifies the behavior in this case:
For message-based sockets such as SOCK_DGRAM and SOCK_SEQPACKET, the entire message must be read in a single operation. If a message is too long to fit in the supplied buffer, and MSG_PEEK is not set in the flags argument, the excess bytes are discarded.
You'll want to increase your buffer on the receive end to be 5000 bytes to account for the entire datagram
I read in MSDN about the send() and recv() function, and there is one thing that I'm not sure I understand.
If I send a buffer of size 256 for example, and receive first 5 bytes, so the next time I call the recv() function, it will point to the 6th byte and get the data from there?
for example :
char buff[256];
memcpy(buff,"hello world",12);
send(sockfd, buffer, 100) //sending 100 bytes
//server side:
char buff[256];
recv(sockfd, buff, 5) // now buffer contains : "Hello"?
recv(socfd, buff,5) // now I ovveride the data and the buffer contains "World"?
thanks!
The correct way to receive into a buffer in a loop from TCP in C is as follows:
char buffer[8192]; // or whatever you like, but best to keep it large
int count = 0;
int total = 0;
while ((count = recv(socket, &buffer[total], sizeof buffer - total, 0)) > 0)
{
total += count;
// At this point the buffer is valid from 0..total-1, if that's enough then process it and break, otherwise continue
}
if (count == -1)
{
perror("recv");
}
else if (count == 0)
{
// EOS on the socket: close it, exit the thread, etc.
}
You have missed the principal detail - what kind of socket is used and what protocol is requested. With TCP, data is octet granulated, and, yes, if 256 bytes was sent and you have read only 5 bytes, rest 251 will wait in socket buffer (assuming buffer is larger, which is true for any non-embedded system) and you can get them on next recv(). With UDP and without MSG_PEEK, rest of a single datagram is lost, but, if MSG_PEEK is specified, next recv() will give the datagram from the very beginning. With SCTP or another "sequential packet" protocol, AFAIK, the same behavior as with UDP is got, but I'm unsure in Windows implementation specifics.
With the following pseudo-Python script for sending data to a local socket:
s = socket.socket(AF_UNIX, SOCK_STREAM)
s.connect("./sock.sock")
s.send("test\n")
s.send("aaa\0")
s.close()
My C program will randomly end up recving the following buffers:
test\n
test\n<random chars>
test\naaa (as expected)
The socket is being recv()'d after select() points that the socket is readable. Question is, how to avoid the first two cases?
And side question: Is it possible to send the following two messages from that script:
asd\0
dsa\0
And have select() to show the socket as readable on each of those sends, or will it only do that if I run the script again (restarting the socket client connection) and sending a message for each connect?
At a guess, the len argument to recv specifies a maximum amount of data to read, not the precise amount to be returned. recv is free to return any amount of data up to len bytes instead.
If you want to read a specific number of bytes, call recv in a loop.
int bytes = 0;
while (bytes < len) {
int remaining = len - bytes;
int read = recv(sockfd, buf+bytes, remaining, 0);
if (read < 0) {
// error
break;
}
bytes += read;
}
As noted by junix, if you'll need to send unpredictable amounts of data, consider defining a simple protocol that either starts each message with a note of its length or ends with a particular byte or sequence of bytes.
This is the snippet of client code:
connect(DescrittoreClient, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
strcpy(Buffer, filename);
send(DescrittoreClient, Buffer, strlen(Buffer), 0);
fd = open(filename, O_CREAT | O_WRONLY,0644);
while ((nread = read(DescrittoreClient, Buffer, sizeof(Buffer))) != 0) {
write(fd, Buffer, nread);
memset(Buffer,0,sizeof(Buffer));
}
int gg;
while( (gg = recv(DescrittoreClient, Buffer, sizeof(Buffer), 0)) == -1) continue;
printf("%d\n", gg);
printf("Risposta del server: %s\n", Buffer);
close(DescrittoreClient);
return EXIT_SUCCESS;
And this is the snippet of the server code:
while(1){
rc = recv(DescrittoreClient, filename, sizeof(filename), 0);
fd = open(filename, O_RDONLY);
fstat(fd, &stat_buf);
offset = 0;
rc = sendfile(DescrittoreClient, fd, &offset, stat_buf.st_size);
if (rc != stat_buf.st_size) {
fprintf(stderr, "incomplete transfer from sendfile: %d of %d bytes\n", rc, (int)stat_buf.st_size);
exit(1);
}
strcpy(Buffer, "Dati inviati correttamente");
if( (send(DescrittoreClient, Buffer, strlen(Buffer), 0)) == -1){
printf("Errore nell'invio della stringa\n");
close(DescrittoreClient);
close(fd);
exit(1);
}
}
close(DescrittoreServer);
return EXIT_SUCCESS;
This is the expected behaviour:
Client --Give me file X--> Server
Server --send the file X--> Client
Server -->send string "File has been sent"--> Client
But this is the real behaviour:
Client --Give me file X--> Server
Server --send the file X--> Client
Server -->_NOTHING_--> Client
So the problem is that the client doesn't receive "File has been sent". I've checked if the problem is server's side but it isn't (in fact the server send the string)
(based on the comments above) -- the thing to realize is that TCP communication is 100% stream based, with no built-in framing. That means that all the TCP layer does is make sure that the receiver receives the bytes in the same order that the sender sent them -- but it does not guarantee that the bytes will be received in the same intervals as they were sent. (For example, if you send() 10 bytes, then 20 bytes, then 50 bytes, the receiver might receive all 80 bytes at once, or 63 bytes followed 17 bytes, or any other combination of recv()s that sum up to 80 bytes total).
Therefore in order to send multiple separate items in such a way that the receiver can interpret them correctly, you need to define your own rules for framing the data. In your case you need to send n bytes of file data, followed by a string, and what your receiving program needs to know is how many bytes of file data to expect. That way, once it has received (that many) bytes, it knows the remaining bytes are string data and won't just write them to the file.
My suggestion would be to send the file's size first (either as a 4-byte integer, or an 8-byte long if you need to support file sizes greater than 4 gigabytes). Then the receiving code would be like this:
Receive 4 bytes
Interpret those four bytes as an integer (you may want to pass this value through htonl() on the sender and ntohl() on the receiver, in order to avoid possible endian-ness issues here)
Receive N bytes and write them to the file
Receive any remaining bytes as a string.