transfer files through sockets in c - c

I want to implement a program that transfer any files from the server to the client. I must use read/write functions to read and write data(its for school assignment). Here is the code for server and client.
server.c
char buffer[512];
if( (file = open(strTable[1], O_RDONLY)) == -1 ) { perror("Open"); }
while( read(file, buffer, sizeof(buffer)) != 0 )
{
size = strlen(buffer)+1;
if( write(newsock, &size, sizeof(size)) < 0 ) { perror("Write"); exit(1); }
write_all(newsock, buffer, strlen(buffer)+1);
}
size = 4;
if( write(newsock, &size, sizeof(size)) < 0 ) { perror("Write"); exit(1); }
write_all(newsock, "end", 4);
It opens strTable[1] (which contains the file that i want to read) it reads sizeof(buffer) bytes and then i send to client how much bytes i will write to socket and after that i send the bytes. Here is write_all function.
int write_all(int sock, char* buffer, int size)
{
int nwrite, sent = 0;
while( sent < size )
{
if( (nwrite = write(sock, buffer + sent, size - sent)) < 0 )
{ perror("Write"); exit(1); }
sent += nwrite;
}
return sent;
}
client.c
if( (file = open(absolute, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1 )
{ perror("Open"); }
while( true )
{
received = 0;
/* Read the desired readable size */
if( read(sock, &size, sizeof(size)) < 0 )
{ perror("Read"); pthread_exit(NULL); }
/* Read all data */
while( received < size )
{
if( (nread = read(sock, buffer + received, size - received)) < 0 )
{ perror("Read"); pthread_exit(NULL); }
received += nread;
}
if( strncmp(buffer, "end", 4) == 0 ) { break; }
write_all(file, buffer, strlen(buffer)+1);
}
The client opens a file (absolute) and writes in it what it reads. It first reads how much size it has to read and then it doesnt stop to read until it reaches that size. If the client reads "end" then server has stop the writing to the socket so the client stops reading.
The problem is that i cant open the files after the transfer. I read some images that i cant open. I read also and one file.txt which i write some random words, this seems to be copied right but it has some garbage too(its the photo number 2). Why i getting this and how can i transfer files from sockets correctly?
enter image description here
enter image description here

Usual problems. read() doesn't null-terminate the buffer, so using strlen() on it as the count isn't valid. A read/write loop should look like this:
int count;
while ((count = read(inFD, buffer, sizeof buffer)) > 0)
{
if (write(outFD, buffer, count) < 0)
{
perrror("write"); // at least
break;
}
}
followed by error-handling as follows:
if (count < 0)
{
perror("read"); // at least
}
Your second problem comes with assuming that "end" will be received by itself as a separate message. There is no guarantee of this. You will either have to use end of stream by closing the socket after each file, or else send the length ahead of each file and only read exactly that many bytes from the stream for each file. But as you are already sending the length, sending "end" is pointless anyway.

Related

net::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK)

I am new in networking and I try to write my first http server on C. However i faced a problem. When i try to send image by chunks i recive an error GET http://localhost/img.jpg net::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK), whith html it works fine.
void answerOnGet(int socketCopy, char *fileName)
{
struct stat sbuf;
char filePath[SIZE];
determinateFilePath(fileName, filePath);
stat(filePath, &sbuf);
char responseHeader[2*SIZE];
char fileType[SIZE];
if (strstr(fileName, ".html") || !strcmp(fileName, "/"))
{
strcpy(fileType, "text/html");
}
else if (strstr(fileName, ".jpg"))
{
strcpy(fileType, "image/jpg");
}
else if(strstr(fileName, ".ico"))
{
strcpy(fileType, "image/ico");
}
else
{
fprintf(stderr, "Type error\n");
exit(1);
}
FILE *fd = fopen(filePath, "rb");
if(fd == NULL)
{
perror("Opening error");
exit(1);
}
snprintf(responseHeader, sizeof(responseHeader),
"HTTP/1.1 200 OK\r\n"
"Transfer-Encoding: chunked\r\n"
"Content-type: %s\r\n\r\n", fileType
);
if(write(socketCopy, responseHeader, strlen(responseHeader)) < 0)
{
perror("Write error");
exit(1);
}
long unsigned sizeOfChunk = 0;
if(sbuf.st_size > SIZE)
{
sizeOfChunk = sbuf.st_size/50;
}
else
{
sizeOfChunk = sbuf.st_size;
}
char *buf = malloc(sizeof(char) * (sizeOfChunk + 2));
printf("Size of chunk = %ld\n", sizeOfChunk);
char amountOfBytes[SIZE];
while(fread(buf, sizeof(char), sizeOfChunk, fd) == (sizeOfChunk))
{
sprintf(amountOfBytes, "%lX\r\n", sizeOfChunk);
puts("\nStart to write");
if(write(socketCopy, amountOfBytes, strlen(amountOfBytes)) < 0)
{
perror("Write bytes error");
exit(1);
}
strcat(buf, "\r\n");
if(write(socketCopy, buf, strlen(buf)) < 0)
{
perror("Write error");
exit(1);
}
puts("\nEnd of write");
bzero(buf, sizeOfChunk);
bzero(amountOfBytes, strlen(amountOfBytes));
}
puts("Send zero chunk");
if(write(socketCopy, "0\r\n\r\n", strlen("0\r\n\r\n")) < 0)
{
perror("Write zero chunk error");
exit(1);
}
fclose(fd);
free(buf);
}
Your mistake is most likely
if(write(socketCopy, buf, strlen(buf)) < 0)
What does strlen(buf) do? It counts the number of bytes up to the first 0 byte.
Is that the correct number of bytes to write? Only if there's a 0 byte at the end and none before that.
Is there? Well, no. Files can have 0 bytes in the middle and fread does not put one at the end.
Instead of strlen(buf) you should use sizeOfChunk.
Other bugs:
As #rveerd pointed out, it's possible that you call write and the kernel only writes part of the data. If that happens, you still have to call it again to write the rest of the data. This may happen multiple times so you need a loop. I suggest making a function actually_write which does the loop, then you can call actually_write(socketCopy, buf, sizeOfChunk)
Your program doesn't send some of the bytes at the end sometimes. If the file is, for example, 1001 bytes long, then you do 20-byte chunks, and after the last full chunk there is still one byte, and fread returns 1 but you don't send the extra byte.

Not sending file correctly. Sockets. C

I am writing a program that a client can ask for files to a server. Then the server will send them in chunks of 512 bytes. The problem is that when the client read the file:
*Sometimes the first 512 bytes are different from the original file. The total read file also has a different size (and obviously it also ends different from the original file) and therefore the client loop that writes to the new file does never end.
*Sometimes it works perfectly and i don't know why.
Server:
/* Check if file exists */
if(access(retrFileName, F_OK) == 0){
/* Open file */
fd = open(retrFileName, O_RDONLY);
lseek(fd, 0, SEEK_SET);
if (fd == -1){
fprintf(stderr, "Error opening file --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
/* Get file stats */
if (fstat(fd, &fileStat) < 0){
fprintf(stderr, "Error fstat --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
sprintf(fileSize, "%li", fileStat.st_size);
/* Sending file data */
offset = 0;
remainData = fileStat.st_size;
while (((sentBytes = sendfile(clientSock, fd, &offset, 512)) == 512) && (remainData > 0)) {
remainData -= sentBytes;
fprintf(stdout, "Server envio %d bytes del file, offset ahora vale: %li y quedan = %d bytes\n", sentBytes, offset, remainData);
}
remainData -= sentBytes;
fprintf(stdout, "Server envio %d bytes del file, offset ahora vale: %li y quedan = %d bytes\n", sentBytes, offset, remainData);//do while
close(fd);////////////////////////
send(clientSock, NICETRANSFER, sizeof(NICETRANSFER), 0); //LO METE AL ARCHIVO
printf("send\n");
//close(clientSock);///////////
}
else{
send(clientSock, FILEERROR, sizeof(FILEERROR), 0);
printf("send\n");
}
}
Client:
/* Open file */
receivedFile = fopen("r.txt", "wb");
if (receivedFile == NULL){
fprintf(stderr, "Failed to open file --> %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
/* Write to the file */
int contador = 0;
int remainData = fileSize;
do{
if(remainData < 512)
bytesLeidos = recv(clientSock, readingBuffer, remainData, 0);
else
bytesLeidos = recv(clientSock, readingBuffer, 512, 0);
fwrite(readingBuffer, bytesLeidos, 1, receivedFile);
remainData -= 512;
contador += 512;
printf("bytesleidos: %li, contador: %d:\n%s\n\n", bytesLeidos, contador, readingBuffer);
}while(contador < fileSize);
fclose(receivedFile);
Golden rule of socket programming: Always check the return value from recv. It's not always what you think it will be.
Even though you "send" 512 bytes at a time, you are in no way guaranteed that TCP will deliver the same number of bytes at a time to the receiver. TCP segmentation, IP fragmentation, and general Internet weirdness will cause the recv side to get an arbitrary number of bytes at a time.
Hence, your hardcoded assumption that recv will always return 512 is incorrect:
remainData -= 512;
contador += 512;
Instead, you should be saying:
remainData -= bytesLeidos;
contador += bytesLeidos;
An you need to check for errors and socket closing too.
This is an improved main loop for your client code:
while (remainData > 0)
{
size_t recvSize = (remainData >= 512) ? 512 : remainData;
bytesLeidos = recv(clientSock, readingBuffer, recvSize, 0);
if (bytesLeidos > 0)
{
fwrite(readingBuffer, bytesLeidos, 1, receivedFile);
remainData -= bytesLeidos;
contador += bytesLeidos;
/* null terminate readingBuffer so garbage isn't printed.*/
/* Make sure readingBuffer is allocated to be at least */
/* N+1 bytes (513) to account for this character being appended. */
readingBuffer[bytesLeidos] = '\0';
printf("bytesleidos: %li, contador: %d:\n%s\n\n", bytesLeidos, contador, readingBuffer);
}
else if (bytesLeidos == 0)
{
/* remote side closed connection */
printf("Remote side exited connection\n");
break;
}
else if (bytesLeidos < 0)
{
/* connection error */
printf("Connection error\n");
break;
}
}
I solved my problem!! I needed to sync both client and server. To do so, the server send the size of the file and waits for an answer for the client with recv. When the client recieve the file size, it send a "" message.
I don't know if this is the correct solution, but this way you can sync server and client.
After sync, the server send the respective file normally with sendfile

Stuck in while when transfer file through socket using TCP

I write program and it works fine, but i want to rewrite it using sendfile() and now i got stuck in a loop.
Server side:
send name = ok
send md5 checksum = ok
send size = ok
send file = ko
Client side:
recv name = ok
recv md5 cecksum = ok
recv size = ok
create dir and create file = ok
write data to created file = ko
P.S In previous version of program i stuck some time to, but it depend how much i use printf why? for e.x i add one line with printf program stuck, delete it, works fine.
UPDT: rewrite code client/server
client
/* Received file name */
int rc_byte = 0;
rc_byte = recv(fd, rx_tx_file->out_name, sizeof(rx_tx_file->out_name),0);
if (rc_byte < 0){
perror("Failed to receive file name: ");
exit(-1);
} else
printf("Recv out name %s\n", rx_tx_file->out_name);
//printf("file name rc %s\n", rx_tx_file->out_name);
trimm_path_name(rx_tx_file);
/* Received md5sum */
rc_byte = recv(fd, rx_tx_file->md5sum, sizeof(rx_tx_file->md5sum), 0);
if (rc_byte < 0) {
perror("Failed to receive check sum: ");
exit(-1);
} else
printf("recv md5s %s\n", rx_tx_file->md5sum);
/* Received file size */
rc_byte = recv(fd, &size, sizeof(size), 0);
if(rc_byte < 0) {
perror("Recevid size of file: ");
exit(-1);
}
printf("%d recv size\n", size);
to_read = size;
if (stat(dir, &st) == -1){
mkdir(dir, 0777);
}
send_data: (add func to server)
void send_data(int client_fd, m_file *rx_tx_file, int option, int size) {
int send_byte = 0;
int total_send = 0;
if (option == SEND_NAME) {
while (total_send < strlen(rx_tx_file->in_name)) {
send_byte = send(client_fd, rx_tx_file->in_name, sizeof(rx_tx_file->in_name),0);
if(send_byte == -1) {
perror("Failed to send file name to client: ");
exit(SEND_TO_CLIENT_ERROR);
}
total_send += send_byte;
}
}
else if (option == SEND_MD5) {
total_send = 0;
send_byte = 0;
while (total_send < strlen(rx_tx_file->md5sum)) {
send_byte = send(client_fd, rx_tx_file->md5sum, sizeof(rx_tx_file->md5sum),0);
if(send_byte == -1){
perror("Failed to send file md5sum to client: ");
exit(-1);
}
total_send += send_byte;
}
}
else if (option == SEND_SIZE) {
send_byte = send(client_fd, &size, sizeof(size),0);
if (send_byte == -1) {
perror("Failed to send size: ");
}
}
}
server:
client_fd = accept(server_fd, (struct sockaddr*) &client_addr, &length)
/*send name of file*/
send_data(client_fd, rx_tx_file, SEND_NAME, 0);
/*send md5 sum*/
take_check_sum(rx_tx_file,rx_tx_file->file_in, 0);
send_data(client_fd, rx_tx_file, SEND_MD5, 0);
/*send size of file*/
size = stats.st_size;
send_data(client_fd, rx_tx_file, SEND_SIZE, size);
remain_data = stats.st_size;
printf("File [%s] ready to send\ncheck sum [%s]\n", rx_tx_file->in_name,rx_tx_file->md5sum);
while (((send_byte = sendfile(client_fd, file_fd, &offset, size)) > 0) && (remain_data > 0))
{
remain_data -= send_byte;
printf("remain %d", remain_data);
}
printf("Succesfully");
Since i work with one client and pass file which should send on server side through command line args, i dont need to wait in while (client_fd = accpet) i just work with one connection and close server. Now its work good. But one question is open, how i should rewrite client side to recv data in a loop. I don't know which size i should recv and because of that i cant write right condition to my while loop. THX all for helping.
TCP is a stream. It has no message boundaries. Your code won't work because of that.
First, you send the name of the file:
send(client_fd, rx_tx_file->in_name, strlen(rx_tx_file->in_name)+1,0)
then you immediately send the md5 sum and then the file size:
send(client_fd, rx_tx_file->md5sum, strlen(rx_tx_file->md5sum)+1, 0)
send(client_fd, &size, sizeof(int),0)
Since the first two strings don't have a fixed number of bytes, it's quite likely that when you try to read the file size or md5 sum from the server you also read the size of the file and maybe even some of the file data.
First, stop trying to put as much of your send and read code as you can into the conditional clause of your if and while statements.
What exactly does
if (send(client_fd, rx_tx_file->md5sum, strlen(rx_tx_file->md5sum)+1, 0) == -1) {
perror("Failed to send file md5sum to client: ");
exit(-1);
}
gain you over
ssize_t bytes_sent = send(client_fd, rx_tx_file->md5sum, strlen(rx_tx_file->md5sum)+1, 0);
if ( bytes_sent < 0 )
{
perror("Failed to send file md5sum to client: ");
exit(-1);
}
Putting all that code into the if clause gains you nothing on the send. And what if strlen(rx_tx_file->md5sum)+1 is 87 and the send() call returns 15? That's a possible return value that your code can't handle because it stuffs everything into the if clause.
ssize_t bytes_sent = send(client_fd, rx_tx_file->md5sum, strlen(rx_tx_file->md5sum)+1, 0);
if ( bytes_sent < 0 )
{
perror("Failed to send file md5sum to client: ");
exit(-1);
}
else if ( bytes_sent < strlen(rx_tx_file->md5sum)+1 )
{
// partial send...
}
That's actually better coded as a loop.
You didn't post your receive code, but if it's in the same style you not only don't gain anything, by putting everything into the if clause you again can't do any decent error detection or correction.
If your file name recv code is similar to
char filename[1024];
if (recv(fd, &filename, sizeof(filename), 0) < 0) {
perror("Failed to read file name: ");
exit(-1);
}
you can't tell what you just received. How many bytes did you just receive? You may have received the file name. You may have received only part of the file name. You may have received the file name, the md5 sum, and some of the file contents itself.
You don't know what you received, and with your code you can't tell. If you zero out the file name and md5 receive buffers and only recv up to one byte less than the size of the buffer, you at least avoid undefined behavior. But if you don't zero out the buffer, or if you read up the the last byte of the buffer, you can also wind up without a nul-terminated string for your filename or md5 sum. And when you then try to treat it as a nul-terminated string you get undefined behavior.
And if you did get extra bytes in the recv calls you make before trying to read the file data, that explains why your code gets stuck - it already read some of the file contents before getting to the loop, so the loop will never see all the content - some of it is gone.
You should avoid using strlen here in your server:
if(send(client_fd, rx_tx_file->in_name, strlen(rx_tx_file->in_name)+1,0) == -1)
Rather just send fixed length string of size sizeof(rx_tx_file->out_name) as you expect in your client
If the filename is smaller just pad it with spaces to make it of length sizeof(rx_tx_file->out_name)
You should also put each receive call in while loop, and add checks that it actually received expected number of bytes, at times recv will just return partial data, you need to post another recv to receive rest of the expected data

client can't read after connection with server in tcp

I wrote function for read and write for a tcp program . I output in server side but I can't get read on client side . my code
read function :
int read_data (int sd , char **data_buf)
{
int in_length,length,size,bytesread;
char *temp_buf;
size = read(sd,&in_length,sizeof(in_length));/*send entire length of data*/
if( 0 > size )
{
printf("Error on reading from socket\n");
exit(1);
}
length = ntohl(in_length);
printf("Total length coming : %d\n",length);
*data_buf =(char *)malloc((length+1)*sizeof(char));
temp_buf =(char *)malloc((length+1)*sizeof(char));
while(length> 0)
{
bytesread = read(sd,temp_buf,4);
strcat(*data_buf,temp_buf);
temp_buf = temp_buf + bytesread;
length = length - bytesread;
}
return 1;
}
and my write functions as :
int write_data (int sd , char *buffer)
{
int length,len_buff,bytesread,size;
len_buff = strlen(buffer);/*total length of string*/
printf("string == %s\n",buffer);
length = htonl(len_buff);/*convert to host to n/w*/
printf("Total length send =%d\n",len_buff);
size = write(sd,&length,sizeof(length));/*write total size to server */
if( 0 > size)
{
printf("error\n");
exit(0);
}
while(length > 0)
{
bytesread = write(sd,buffer,4);/*write 4 bytes to server*/
buffer = buffer + bytesread;
length = length - bytesread;
}
return 1;
}
client program :
///.............code for socket and connections.................//
ret = write_data(sd,user_string);/*write entire datas to server*/
value_from_server = read_data(sd,&data_buf);
server side program :
value_from_client = read_data(connfd,&data_buf);
printf("the value from client : %s\n",data_buf);
index = string_function(data_buf,&store_buf);
printf("after string process : %s\n",store_buf);
write_data(connfd,store_buf);
printf("i am waiting for next string\n");
connfd is the new socket for communication with client . reading and writing function work perfectly on server side . writing function work on client side . but reading from server not work in client program . ant mistake on my code ?
bytesread = read(sd,temp_buf,4);
Why read 4 bytes always inside the loop? You should be reading the remaining number of bytes to be read. The socket is blocking and hence will be stuck if the server is done sending but client still tries reading 4 bytes to arrive in the last iteration.
Have print statements inside the loop to know the bytes read in each iteration and see if client is blocked with read
Your code has several logic errors.
size = read(sd,&in_length,sizeof(in_length));/*send entire length of data*/
if( 0 > size )
{
printf("Error on reading from socket\n");
exit(1);
}
length = ntohl(in_length);
Here you are assuming you read four bytes, rather than fewer, or end of stream. You must check for end of stream (zero return value), and you must loop until you get the four bytes.
while(length> 0)
{
bytesread = read(sd,temp_buf,4);
strcat(*data_buf,temp_buf);
temp_buf = temp_buf + bytesread;
length = length - bytesread;
}
Here again you are ignoring the possibility of end of stream or an error. It should be:
while ((bytesread = read(sd,temp_buf, length)) > 0)
{
temp_buf += bytes_read;
length -= bytesread;
}
if (bytesread < 0)
{
perror("read 2");
}
else if (length > 0)
{
// end of stream before all expected bytes were received ...
}
else
{
// The OK case
}
Your sending code is suboptimal:
while(length > 0)
{
bytesread = write(sd,buffer,4);/*write 4 bytes to server*/
buffer = buffer + bytesread;
length = length - bytesread;
}
There's no point in chunking into 4-byte writes. It should be:
while (length > 0)
{
bytesread = write(sd, buffer, length);
buffer = buffer + bytesread;
length = length - bytesread;
}
and of course the misnamed bytesread variable should be called byteswritten. In fact you can rely on this loop only executing once. Again it should be followed by a test of byteswritten == -1 to check for errors.
Your functions have logic errors in them.
The reading loop is reading exactly 4 bytes on each iteration. If the length of the data being read is not an even multiple of 4, read() will block on the last iteration waiting for data that does not arrive. The reading loop is also assuming that read() returns a null-terminated buffer, but that is not the case, so strcat() will attempt to copy data from surrounding memory and will either copy garbage or crash with a segfault. Also, the reading function is not null-terminating the data buffer it returns to the caller, but the caller assumes it is null-terminated.
The writing loop is writing exactly 4 bytes on each iteration. If the length of the data is not an even multiple of 4, write() will attempt to write data from surrounding memory on the last iteration, and will either send garbage or crash with a segfault.
You are also not doing adequate error handling in either function.
Try something more like this instead:
void read_raw_bytes (int sd, void *data, int length)
{
int bytes_read;
char *data_ptr;
data_ptr = (char*) data;
while( length > 0 )
{
bytes_read = read(sd, data_ptr, length);
if( bytes_read < 0 )
{
printf("Error on reading from socket\n");
exit(1);
}
if( bytes_read == 0 )
{
printf("Disconnected while reading from socket\n");
exit(1);
}
data_ptr += bytes_read;
length -= bytes_read;
}
}
void write_raw_bytes (int sd, void *data, int length)
{
int bytes_sent;
char *data_ptr;
data_ptr = (char*) data;
while( length > 0 )
{
bytes_sent = write(sd, data_ptr, length);
if( bytes_sent < 0 )
{
printf("Error on writing to socket\n");
exit(0);
}
data_ptr += bytes_sent;
length -= bytes_sent;
}
}
int read_data (int sd, char **data_buf)
{
int length;
read_raw_bytes (sd, &length, sizeof(length)); /*send entire length of data*/
length = ntohl(length);
printf("Total length coming : %d\n", length);
*data_buf = (char *) malloc((length+1)*sizeof(char));
if (*data_buf == NULL)
{
printf("Error on allocating memory\n");
exit(1);
}
read_raw_bytes (sd, *data_buf, length);
(*data_buf)[length] = 0;
return 1;
}
int write_data (int sd, char *buffer)
{
int length, len_buff;
len_buff = strlen(buffer); /*total length of string*/
printf("string == %s\n", buffer);
printf("Total length send =%d\n", len_buff);
length = htonl(len_buff); /*convert to host to n/w*/
write_raw_bytes (sd, &length, sizeof(length)); /*write total size to server */
write_raw_bytes (sd, buffer, len_buff);
return 1;
}

C Socket client prints out a strange output

I'm trying to send a .txt file to a Linux socket client from a Linux server client (I use the loopback interface). I tried to a send a string, i.e. "OK", and everything worked fine, but when I try to send a file, the client prints out a strange output. Obviously I've done all the previous steps like socket, connect, accept, listen etc.
This is the server-side code:
printf("Sending file\n);
if ((fp=fopen(filename, "r"))!=NULL){
while ( (nbytes = fread(sendline, sizeof(char), 512, fp) > 0)){
printf("%s\n",sendline);
sent = writen(clientfd, sendline, nbytes);
}
close(fp);
}else
perror("Open file");
The 'writen' function is:
ssize_t writen(int fd, const void *vptr, size_t n){
/* Write "n" bytes to a descriptor. */
size_t nleft;
ssize_t nwritten;
const char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
if (nwritten < 0 && errno == EINTR)
nwritten = 0; /* and call write() again */
else
return(-1); /* error */
}
nleft -= nwritten;
ptr += nwritten;
}
return(n);
}
The client-side code is:
while (fgets(sendline, 10000,stdin) != NULL)
{
sendto(sockfd,sendline,strlen(sendline),0,
(struct sockaddr *)&servaddr,sizeof(servaddr));
read(sockfd,recvline,10000);
fputs(recvline,stdout);
recvline[n]=0;
if((recvline[0]=='-')&&(recvline[1]=='E')&&(recvline[2]=='R')&&(recvline[3]=='R')){
close(sockfd);
exit(1);
}
}
The strange client that I get is in the image.
Client Output
So what's my mistake? Why do I receive this kind of output and how could I fix it?
Couple of issues,
In server code, parenthesis is at incorrect place,
while ( (nbytes = fread(sendline, sizeof(char), 512, fp) > 0)){
should be
while ( (nbytes = fread(sendline, sizeof(char), 512, fp)) > 0){
---------^ parenthesis close here
And in client side, set '\0' in recvline before printing as
n = read(sockfd,recvline,10000);
recvline[n] = '\0'
fputs(recvline,stdout);
You never check how many bytes read returned (or whether it failed). Even if it does return n bytes as you assume, you don't null-terminate the buffer until after you print it, so fputs(recvline,stdout) will print whatever garbage it finds in the uninitialized buffer on the stack.

Resources