Not receiving full data - c

I have the following socket code in C. I am trying to receive 70 bytes of data on each cycle. However, I am getting only 4 bytes of data. The full data is something like this (in hex):
4D43475000856308000004B2DE1F04009E00200100000000696CF7AB002F1A00000000
000000325C000402069BFDE70857E22502F41C000036000000DF0B0932100B09DC0719
What is the problem? I have tried to research many StackOverflow answers, but with no help.
The code is as below:
void doprocessing (int sock);
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, portno, clilen;
char buffer[1024];
struct sockaddr_in serv_addr, cli_addr;
int n, pid;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 14064;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
listen(sockfd,5000);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* Create child process */
pid = fork();
if (pid < 0) {
perror("ERROR on fork");
exit(1);
}
if (pid == 0) {
/* This is the client process */
close(sockfd);
doprocessing(newsockfd);
exit(0);
}
else {
close(newsockfd);
}
} /* end of while */
}
void doprocessing (int sock)
{
int n,i;
unsigned int *buffer = malloc(1024);
n = read(sock,buffer,1023);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("Here is the message: %.4x\n",*buffer);
n = write(sock,"MCGP",18);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
free(buffer);
}

There are quite a number of bugs in your code:
clilen = sizeof(cli_addr); needs to be moved inside of the while loop above the accept() call.
unsigned int *buffer should be unsigned char *buffer instead.
Why are you reading 1023 bytes when you are only expecting 70 bytes?
You need to call read() in a loop until you actually receive all of the bytes you are expecting. read() can return fewer bytes than requested. TCP is a byte stream, it has no concept of message boundaries, the read will return whatever bytes are currently available, so it will return at least 1 byte up to the requested number of bytes.
Your printf() call is only outputting the first 4 bytes of buffer, it is not outputting the full content of buffer. The return value of read() tells you how many bytes were actually received. Loop through the buffer outputting each byte individually.
write(sock,"MCGP",18) is a buffer overflow, since you are only passing 5 bytes (4 characters and the null terminator) but are telling it to send 18 bytes instead.
Try this instead:
void doprocessing (int sock);
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, portno;
struct sockaddr_in serv_addr, cli_addr;
socklen_t clilen;
int pid;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR creating socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 14064;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on bind");
exit(1);
}
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
if (listen(sockfd, SOMAXCONN) < 0) {
perror("ERROR on listen");
exit(1);
}
while (1) {
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* Create child process */
pid = fork();
if (pid < 0) {
perror("ERROR on fork");
exit(1);
}
if (pid == 0) {
/* This is the client process */
close(sockfd);
doprocessing(newsockfd);
exit(0);
}
else {
close(newsockfd);
}
} /* end of while */
}
void doprocessing (int sock)
{
int n, i;
unsigned char buffer[70], *p = buffer;
size_t len = 70;
do {
n = read(sock, p, len);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
if (n == 0) {
perror("DISCONNECTED unexpectedly");
exit(1);
}
p += n;
len -= n;
}
while (len > 0);
printf("Here is the message: ");
for (i = 0; i < 70; ++i)
printf("%.02x", buffer[i]);
printf("\n");
n = write(sock, "MCGP", 4);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
}

Related

Client hangs when tries to read back from server tcp

i am trying to create a simple tcp server-client. My programm works fine if client sends data to server but when server tries to answer back the whole connection hangs. I am using write()/read() functions .
Server code :
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <stdbool.h>
#define SIZE 700000000
///////////////////////////////////////////////////////////////////////////
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 5001;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
listen(sockfd, 10);
clilen = sizeof(cli_addr);
/* Accept actual connection from the client */
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
bzero(buffer, 255);
int readbyte = 0;
do {
readbyte = read(newsockfd, buffer, 1024);
if (readbyte < 0)
{
perror("ERROR on reading socket!");
break;
}
if (readbyte > 0)
{
//printf("Here is the message: %s\n",buffer);
}
} while (readbyte > 0); /* until EOF */
int writen = write(newsockfd, "I received your message", strlen("I received your message") + 1);
if (writen<0){
perror("Error");
}
//debug();
return 0;
}
Client code:
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
//////////////////////////////////////////////////////////////////
int main(int argc, char *argv[]) {
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
int mode;
char *code;
char buffer[256];
char *uptr = buffer;
int i;
if (argc < 3) {
fprintf(stderr, "Use: %s [hostname] [port] [args]\n", argv[1]);
exit(0);
}
portno = atoi(argv[2]);
/* Create a socket point */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr, "ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno);
int sock_et = connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr);
/* Now connect to the server */
if (sock_et < 0) {
perror("ERROR connecting");
exit(1);
}
/* some code... */
while (len > 0) {
int writen = write(sockfd, buf, len + 1);
if (writen < 0)
{
printf("Error writting to socket!\n");
break;
}
len -= writen;
buf += writen; /* tricky pointer arythmetic */
}
printf("Finished writing to server\n");
bzero(buffer, 256);
int readbyte;
do {
readbyte = read(sock_et, buffer, 1024);
if (readbyte < 0)
{
perror("ERROR on reading socket!");
break;
}
if (readbyte > 0)
{
//printf("Here is the message: %s\n",buffer);
}
} while (readbyte > 0); /* until EOF */
printf("%s\n",buffer );
close(sockfd);
return 0;
}
Any help would be appreciated! Thanks!
Your client code doesn't compile
You are never going to get a 0 (EOF) from read while the socket is open (in either the client or server) -- so just add a break after a successful read for now.
You are not closing the socket in the server
In the client, you need to read from sockfd, not sock_et
There are probably other issues. It looks like you are trying to use client.c/server.c from here: http://www.linuxhowtos.org/C_C++/socket.htm
If I use those files, it works fine. So start over from them and apply your changes more carefully.

MPI and Socket programming - Notify if no process found the file searching

I have an assignment to combine MPI and Socket programming for searching a file. MPI will be used to create processes which search into folders whereas sockets will be used for sending and receiving messages. My only problem right now is how I notify my master process if no file was found. Everything else is working fine.
Here is my code:
int main(int argc, char** argv)
{
int rank, size;
DIR *d;
FILE *fp;
struct dirent *dir;
if (argc < 2) {
error("Ju lutem jepni emrin e file.");
}
printf("Fillon kerkimi...\n\n");
// Initialize the MPI environment.
MPI_Init(&argc, &argv);
// Get the number of processes
MPI_Comm_size(MPI_COMM_WORLD, &size);
// Get the rank of the process
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0) {
server();
} else {
char str[100];
sprintf(str, "./%d/%s", rank, argv[1]);
//if file is found
if ((fp = fopen(str, "r")) != NULL) {
char buffer[4096];
int i=0;
char c;
while((c = getc(fp)) != EOF)
{
buffer[i++] = c;
}
buffer[i]='\0';
client(buffer);
}
}
MPI_Finalize();
return 0;
}
The server() and client() functions are used for sending and receiving using sockets. Didn't post the code because it is working fine.
Any ideas?
EDIT:
Server code:
void server() {
int sockfd, newsockfd, clilen;
char buffer[MAX_LEN];
struct sockaddr_in serv_addr, cli_addr;
int n;
struct timeval timeout;
timeout.tv_sec = 3;
timeout.tv_usec = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
error("ERROR opening socket");
}
//clear
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(PORTNO);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
error("ERROR on binding");
}
if (setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
sizeof(timeout)) < 0) {;
printf("File nuk u gjend!");
return;
}
listen(sockfd,5);;
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
{
error("ERROR on accept");
}
bzero(buffer, 256);
if (read(newsockfd, buffer, 255) < 0)
{
error("ERROR reading from socket");
}
close(newsockfd);
close(sockfd);
printf("File output: \n%s\n", buffer);
return;
}
Client code:
void client(char* msg[]) {
int sockfd, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
strcpy(buffer, msg);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
error("ERROR opening socket");
}
server = gethostbyname("localhost");
if (server == NULL)
{
fprintf(stderr, "ERROR no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy( (char *) server->h_addr,
(char *) &serv_addr.sin_addr.s_addr,
server->h_length
);
serv_addr.sin_port = htons(PORTNO);
while(1)
{
if (connect(sockfd, &serv_addr, sizeof(serv_addr)) >= 0)
break;
}
if (write(sockfd, buffer, strlen(buffer)) < 0)
{
error("ERROR writing to socket");
}
close(sockfd);
return;
}
Note: I'm using setsockopt() on the server function which seems to work well for a timeout and do the job, though it doesn't let me print my own message to the console.

multi-process in C : global variable's value

Here is the code from a website. It used multi-processing to create a server. My question is: will the parent process close(newsockfd) executed before the child process doprocessing(newsockfd) ?
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
void doprocessing (int sock);
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n, pid;
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 5001;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* Create child process */
pid = fork();
if (pid < 0) {
perror("ERROR on fork");
exit(1);
}
if (pid == 0) {
/* This is the client process */
close(sockfd);
doprocessing(newsockfd);
exit(0);
}
else {
close(newsockfd);
}
} /* end of while */
}
===-=================
void doprocessing (int sock) {
int n;
char buffer[256];
bzero(buffer,256);
n = read(sock,buffer,255);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("Here is the message: %s\n",buffer);
n = write(sock,"I got your message",18);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
}
==========-==========================
code is from this website:
http://www.tutorialspoint.com/unix_sockets/socket_server_example.htm
When the process is forked, the gets a copy of the open set of file desriptors, and the reference count on the open filess is incremented accordingly. The close only happens in the parent process, so the child still maintains a reference to the open file. The order of execution doesn't really matter. On a multi-cpu system, it may happen truly simultaneously.
Global variables are not shared by forked child processes. A forked process runs in its own virtual memory space.

Why am i getting a "Invalid argument" errno returned by my accept() socket function?

When i run this source code it is fine up until it receives a request from the client for an invalid file name, following that all connection attempts are failures with this code--"Invalid Argument" When i try to accept.
Here is the source code, written in C.
enter code here
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "pthread.h"
#include <errno.h>
#define BACKLOG 10
void *handle_client(void *); //Function for processing threads
int main ()
{
int sockfd, portno, tempsockfd, optval;
struct sockaddr_in serv_addr, cli_addr;
socklen_t *clilen;
pthread_t thread_id;
FILE* fp = NULL;
char buff[100];
memset(buff,0,sizeof(buff));
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("ERROR with server socket()");
exit (1);
}
puts("Socket creation was successful\n");
srand (time (NULL));
portno = (rand() % 10000) + 1;
while (portno < 1000)
{
portno = (rand() % 10000) +1;
}
printf ( "%d\n", portno);
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
optval = 1;
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&optval, sizeof(optval));
puts("Attempting to bind socket...\n");
/* Binding the host ID to the socket.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
perror("ERROR with server bind()\n");
exit(1);
}
puts ("Socket Bound\n");
/* Listen for clients until "BACKLOG" is reached. */
if ((listen(sockfd,BACKLOG)) != 0)
{
perror("Failure to listen, bad socket\n");
exit(1);
}
*clilen = sizeof(cli_addr);
puts ("Now listening...\n");
tempsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, (socklen_t *)&clilen);
if (tempsockfd <0)
{
printf ("BADCONNECTIOn...Error: %s\n", strerror(errno));
exit(1);
}
puts("Connection accepted");
//Get the socket descriptor
int newsockfd = tempsockfd;
char buffer[256];
int n;
int c;
int x = 0;
/* If successful connection, begin reading from file. */
bzero(buffer,256);
n = read( newsockfd,buffer,255 );
if (n < 0)
{
perror("ERROR server cannot read file.\n");
exit(1);
}
printf("The file name is: %s\n", buffer);
fp = fopen(buffer, "rw+");
if (fp==NULL)
{
perror("File could not be opened\n");
n = write(newsockfd,"ERROR:FILE NOT FOUND",20);
if (n < 0)
{
perror("ERROR writing to client.\n ");
exit(1);
}
exit(1);
}
while ((c = fgetc(fp)) != EOF)
{
if (x == 255)
{
/* Relay file contents to the client */
n = write(newsockfd,buffer,x);
if (n < 0)
{
perror("ERROR writing to client.\n ");
exit(1);
}
x = 0;
}
buffer[x] = (char) c;
x++;
}
/* Relay file contents to the client */
n = write(newsockfd,buffer,x);
if (n < 0)
{
perror("ERROR writing to client.\n ");
exit(1);
}
return 0;
}
socklen_t *clilen;
*clilen = sizeof(cli_addr);
This is undefined behavior. clilen is not initialized and then dereferenced.
tempsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, (socklen_t *)&clilen);
You are casting a pointer of type socklen_t** to socklen_t*. This could not possibly have any sense whatsoever.
Change this to
socklen_t clilen;
clilen = sizeof(cli_addr);
tempsockfd = accept(sockfd, (struct sockaddr*)&cli_addr, &clilen);
Note the absence of cast in the last argument. Do not insert casts to silence compiler messages, especially when you are not sure what type you really need.

String with thread in tcp client / server in C

I'm trying to develop an application in C to receive a message and send it in TCP. For that, I'm using a 2 threads : the server thread to listen and a client thread to send it.
Here the server and the main function :
void dostuff(int sock)
{
int n;
char buffer[256];
bzero(buffer,256);
n = read(sock,buffer,255);
if (n < 0) error("ERROR reading from socket");
else {
pthread_t t_tcp_client;
pthread_create(&t_tcp_client, NULL, tcp_client, buffer);
}
n = write(sock,"Message received",18);
if (n < 0) error("ERROR writing to socket");
}
static void *tcp_server(void *p_data)
{
int sockfd, newsockfd, pid;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(TCP_PORT);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) error("ERROR on accept");
pid = fork();
if (pid < 0) error("ERROR on fork");
if (pid == 0) {
close(sockfd);
dostuff(newsockfd);
exit(0);
} else {
close(newsockfd);
}
}
close(sockfd);
return 0;
}
int main (void)
{
pthread_t t_tcp_server;
pthread_create(&t_tcp_server, NULL, tcp_server, NULL);
pthread_join(t_tcp_server, NULL);
return 0;
}
And the client thread :
static void *tcp_client(void *p_data)
{
if (p_data != NULL)
{
char const *message = p_data;
printf("Message transmitted : %s\n", message);
}
return 0;
}
The problem is that the client thread doesn't receive the good char, the result is :
Message transmitted : ???~?
I think the problem comes from the line : n = read(sock,buffer,255); but I don't really understand why.
Thank you for your help
static char buffer[256];
void dostuff(int sock)
{
int n;
bzero(buffer,256);
n = read(sock,buffer,255);
...
}
Be careful when using sockets, one read may don't give you the totality of the message you wait.
In case of structured messages, the protocol you define (you should define it well) have to give a message identifier at first, and you read until you receive sizeof( theSpecificMessage ), theSpecificMessage is identified by the identifier.
do_stuff most likely exited before the client thread did it's work.
The client thread uses stack allocated memory which then had been freed when do_stuff exited, and will be reused by some other code.
A solution to this would be to pass heap allocated memory to the client. If allocated dynamically the latter then needs to be freed by the client after it has done its work.

Resources