I see a plenty of examples but none addresses what I want to accomplish. I need to read the bytes from a socket and write them in to a file. In this Code Project blog I see where in the client script a while loop iterates through a read call:
while((n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
So I modified the code do that fputs(recvBuff, f1) where f1 is a pointer to a pdf file. A pdf file is also a file I'm fetching from the server so I need to reassemble it, however the fputs operated with a string and corrupts the file, so I need a byte "writer" so fwrite would have been the choice but I can't get fwrite to work. I ended up modifying my code to resemble some of the examples to test it out but to no avail.
If in fwrite the first parameters is the 'data' how would I pass it? I've tried the read() call as in the while loop above but that seem to return an integer rather then a byte stream. Any ideas?
I'm new to programming but am new to C and would appreciate a little push in a right direction. Thanks.
You want something more like this. fwrite doesn't return a stream it returns the number of items (i.e. the 3rd parameter) successfully written. In this case the "item" is a single char and you are attempting to write "bytesRead" number of them. Good form dictates that you should check that the result fread returns is the same as you requested be written but this rarely fails on a disk file so many people skip it in non-critical situations. You may want to add that on yourself.
FILE *f1;
int sockfd;
char recvBuff[4096];
size_t bytesWritten;
ssize_t bytesRead;
while((bytesRead = read(sockfd, recvBuff, sizeof(recvBuff))) > 0)
bytesWritten = fwrite(recvBuff, 1, bytesRead, f1);
Related
I am trying to send a file and its name through a socket in C.
The relevant server code is:
char file[18];
memset(file, 0, 18);
file[17] = '\0';
int recvd = recv(newsock, file, 16, 0);
char local_file_path[200];
memset(local_file_path, 0, 200);
if(recvd == -1 || recv == 0) {
fprintf(stderr, "File name not received");
continue;
}
strcat(local_file_path, "/home/ubuntu/results/");
strcat(local_file_path, file);
FILE* fp = fopen(local_file_path, "wb");
char buffer[4096];
while(1)
{
recvd = recv(newsock, buffer, 4096, 0);
fwrite(buffer, sizeof(char), recvd, fp);
if(recvd == -1 || recvd == 0) {
fclose(fp);
break;
}
}
close(newsock);
}
close(servSock);
The relevant client code is:
char* my_16_long_fname = "filename1234.txt"
int ret = send(sock, my_16_long_file_fname, strlen(my_16_long_fname), 0)
This code, however, has been creating lots of undefined behaviour such as:
1.Receiving garbage filenames filled with garbage
2.Receiving empty files (so a name with nothing inside - could be some other bug but possibly due to this)
I have thought about a few solutions:
1.Diferentiate file types by signature/header and generate a file name on the server side. Besides this being a cheap solution which doesn't teach me how to actually solve the problem, it doesn't work with the logic i'm using, where sometimes I send error codes instead of file names after opening the socket.
2.Iterate over the recv'd buffer on the first call to recv until I encounter a '\0' character. Then write the remainder of the buffer as binary data and keep on receiving data as usual.
Is this the most efficient/simplest and solid solution to this issue, which will prevent any undefined behaviour?
There is no way your current code could possibly work. If the filename is always one character, your code can read too many characters. If your filename is always the same number of characters but more than one character, your code can read too few characters. If the filename is a variable number of characters, your code could read a smaller number than was sent.
So there is no sending protocol for which this could be valid receiving code.
Until you are an expert on writing networking code, always follow these two steps:
Document the protocol.
How many bytes does the filename occupy? Is it a fixed number or a variable number? Is it always followed by a zero byte?
Implement the protocol.
For example, your code reads up to 16 bytes for the filename. But it never checks if it received the whole file name. What if it only received a single byte?
I have this sample code where I'm trying to implement for my operating systems assignment a program that copies the contents of an input file to an output file. I'm only allowed to use POSIX system calls, stdio is forbidden.
I've thought about storing the contents in a buffer but in my implementation I must know the file descriptor contents size. I googled a little and found about
off_t fsize;
fsize = lseek (input, 0, SEEK_END);
But in this case my file descriptor (input) gets messed up and I can't rewind it to the start. I played around with the parameters but I can't figure a way to rewind it back to the first character in the file after using lseek. That's the only thing I need, having that I can loop byte by byte and copy all the contents of input to output.
My code is here, it's very short in case any of you want have to take a look:
https://github.com/lucas-sartm/OSAssignments/blob/master/copymachine.c
I figured it out by trial and error. All that was needed was to read the documentation and take a look at read() return values... This loop solved the issue.
while (read (input, &content, sizeof(content)) > 0){ //this will write byte by byte until end of buffer!
write (output, &content, sizeof(content));
}
I am designing an image decoder and as a first step I tried to just copy the using c. i.e open the file, and write its contents to a new file. Below is the code that I used.
while((c=getc(fp))!=EOF)
fprintf(fp1,"%c",c);
where fp is the source file and fp1 is the destination file.
The program executes without any error, but the image file(".bmp") is not properly copied. I have observed that the size of the copied file is less and only 20% of the image is visible, all else is black. When I tried with simple text files, the copy was complete.
Do you know what the problem is?
Make sure that the type of the variable c is int, not char. In other words, post more code.
This is because the value of the EOF constant is typically -1, and if you read characters as char-sized values, every byte that is 0xff will look as the EOF constant. With the extra bits of an int; there is room to separate the two.
Did you open the files in binary mode? What are you passing to fopen?
It's one of the most "popular" C gotchas.
You should use freadand fwrite using a block at a time
FILE *fd1 = fopen("source.bmp", "r");
FILE *fd2 = fopen("destination.bmp", "w");
if(!fd1 || !fd2)
// handle open error
size_t l1;
unsigned char buffer[8192];
//Data to be read
while((l1 = fread(buffer, 1, sizeof buffer, fd1)) > 0) {
size_t l2 = fwrite(buffer, 1, l1, fd2);
if(l2 < l1) {
if(ferror(fd2))
// handle error
else
// Handle media full
}
}
fclose(fd1);
fclose(fd2);
It's substantially faster to read in bigger blocks, and fread/fwrite handle only binary data, so no problem with \n which might get transformed to \r\n in the output (on Windows and DOS) or \r (on (old) MACs)
I want to read all buffers from a pipe except for the last one. This is my current code:
while(read(server_to_client,serverString2,sizeof(serverString2))){
printf("Client : PID %d",getpid());
printf("-Target>>%s<<", clientString2);
printf(serverString2);
}
The problem with that is it reads everything from the buffer. How can I avoid reading the last buffer?
You can't. The question does not even make sense.
The question supposes that a "buffer" is a meaningful unit of measure for your data, but it is not. In particular, the third argument to read(2) is a maximum number of bytes to read, but the call may actually transfer fewer bytes for a large number reasons, with reaching the end of the data being only one. Other reasons are in fact a lot more likely to manifest when the file descriptor being read is connected to a pipe, as you say yours is, than when it is connected to a file. Note that this means you must always capture read()'s return value if you intend to examine the data it reads, for otherwise you cannot know how much of the buffer contains valid data.
More generally, you cannot tell from an open file descriptor for a pipe how much data is available to be read from it. You need to include that information in your protocol (for example, HTTP's Content-Length header), or somehow communicate it out-of-band. That still doesn't tell you how much data is available to be read right now, but it can help you determine when to stop trying to read more.
Edited to add:
If you ask because you want to avoid dealing with partially-filled buffers, then you are flat out of luck. At minimum you need to be prepared for a partially-filled buffer when the data are prematurely truncated. Unless the total size of the data to be transferred is certain to be a multiple of the chosen buffer size, you will also have to be prepared to deal with a partial buffer at the end of your data. You can, however, avoid dealing with partial buffers in the middle of your data by repeatedly read()ing until you fill the buffer, perhaps via a wrapper function such as this:
ssize_t read_fully(int fd, void *buf, size_t count) {
char *byte_buf = buf;
ssize_t bytes_remaining = count;
while (1) {
ssize_t nread = read(fd, byte_buf, bytes_remaining);
if ((nread <= 0) || ((bytes_remaining -= nread) <= 0)) {
break;
}
byte_buf += nread;
bytes_remaining -= nread;
}
return count - bytes_remaining;
}
Alternatively, you can approach the problem altogether differently. Instead of trying to avoid reading certain data, you may be able to read it but avoid processing it. Whether that could be sensible depends on the nature of your program.
Do you really need to avoid reading the last buffer? Or just avoid doing anything with it? Perhaps a different form of loop? Perhaps a check for eof() after reading each buffer?
while(read(server_to_client,serverString2,sizeof(serverString2)))
{
if (! eof(server_to_client))
{
printf("Client : PID %d",getpid());
printf("-Target>>%s<<", clientString2);
printf(serverString2);
}
else
{
// do special stuff for the last buffer here
}
}
I'm working on a proxy server in c. I've gotten rather far using a combination of fread and fgets in different places but would like to reconcile and understand the difference. In the following example, I'm trying to use fread in a place i previously used fget successfully. Instead my server now hangs at the fread line. What's the difference and why is my program hanging?
void HandleTCPClient(int clntSocket)
{
FILE *request = fdopen(clntSocket, "r");
char reader[2000];
size_t q; //typo before
while((q=fread(reader, 1, sizeof(reader), request))>0) { //hangs here!
printf("i read something!\n");
}
return;
}
thanks!!
EDIT: so if i make the line "while((q=fread(reader, 1, 1, request))>0) {"
i get "i read something" all over my screen...
not sure what this means. So is it correct that fread will literally do nothing if there isn't at least your buffer's size number of characters present in the stream?
fgets returns when a newline is read while fread will block until requested number of bytes are available in the stream or on EOF. In your case, the call blocks because you do not have 2000 bytes of data ready in the stream.
Using fread() instead of recv() to read on a TCP socket seems strange to me..?
Anyway, fread is blocking as long as there is nothing to read. You should always check that a socket is ready to perform reading or writing, using select() for example on linux.