Trouble reading data from client to server - c

I am having trouble reading values from a client from my server/client program. User are supposed to enter a country in the client and the server are supposed to process the value and then return the information (capital, currency) related to the country.
For my program, the server is able to return the correct data for the first time. For example, user key in China, the server will return the capital as beijing etc..
However, when the user entered for example 'Germany' for the second time, the server does not return any data at all.
Hope you guys can identify the error in my codes. Thanks in advance!
Thanks in advance!

On client side, after printing received answer you're closing clientFd and not trying to reconnect for further use. In fact for second time write is doing on a closed file descriptor. One solution is this:
while (1) {
/* Create a socket, bidirectional, default protocol */
clientFd = socket(AF_LOCAL, SOCK_STREAM, DEFAULT_PROTOCOL);
do { /* Loop until a connection is made with the server */
result = connect(clientFd, serverSockAddrPtr, serverLen);
printf("Attempting to connect...\n");
if (result == -1) sleep(1); /* Wait and then try again */
} while (result == -1);
char country[300];
printf("%s \n", " ");
printf("Please enter country > ");
fflush(stdout);
fgets(country, sizeof(country), stdin);
printf("%s \n", " ");
if (0 == strcmp(country, "end\n")) {
printf("Thank you for using country services\n");
exit(0);
} else {
write(clientFd, country, strlen(country));
parse(clientFd);
}
close(clientFd);
printf("%d\n", clientFd);
clientFd = 0;
}

Related

scanf() not working after ENTER

I'm making this simple example from server to client where the server functions as a echo server! So the client gets input from the user and sends it to the server, the server then sends it back.
I just got stuck on the input from the user. I used stuff like getchar, scanf and fgets. But when I start typing and press ENTER, then it should continue to the next thing in the program... Sadly that ain't happening.
Here is my code for the message part:
while(1)
{
char message[1000], servermessage[1000];
printf("You: ");
scanf("%s", message);
printf("%s\n", message);
if (send(sock, message, strlen(message), 0) < 0)
{
printf("sending failed\n");
return (EXIT_FAILURE);
}
int received = recv(sock, servermessage, sizeof(servermessage), 0);
if (received < 0)
{
printf("received failed\n");
return (EXIT_FAILURE);
}
servermessage[received] = '\0';
printf("Server: %s\n", servermessage);
}
close(sock);
After you type the first time, you call recv(), it will block until there is some data to read, you client didn't read any data, so nothing happen. You need check your echo server to find what's wrong. If you need a echo server to test your client, you can use the code for server here.

How to use recv to recieve long text strings

I am trying to create a server and client program that sends a string from client to server where the server executes that string and sends the output back to the client. I am doing this in linux and I am very confused why my program isnt working the least bit. Here is the code.
**Client**
int main()
{
//Code to use unix socket here
if (connect(s, (struct sockaddr *)&remote, len) == -1) {
perror("connect");
exit(1);
}
printf("Connected.\n");
while(printf("> "), fgets(str, MAX, stdin), !feof(stdin)) {
if (send(s, str, strlen(str), 0) == -1) {
perror("send");
exit(1);
}
}
done=0;
do {
if(t=recv(s, str, MAX, 0)<0)
perror("recv failed at client side!\n");
str[t] = '\0';
if(strcmp(str, "ENDOFTRANS")==0)
{
printf("\nRead ENDOFTRANS. Breaking loop.\n");
done=1;
}
printf("Server > %s", str);
} while(!done);
}
And then the server code is:
**Server**
#define MAX 1000
int main(void)
{
//Unix socket code
//This process is now a daemon.
daemon();
//Listens for client connections, up to 5 clients can queue up at the same time.
if (listen(s, 5) == -1) {
perror("listen");
exit(1);
}
for(;;) {
int done, n, status;
printf("Waiting for a connection...\n");
t = sizeof(remote);
if ((newsock= accept(s, (struct sockaddr *)&remote, &t)) == -1) {
perror("accept");
exit(1);
}
printf("Connected.\n");
done = 0;
do {
switch(fork())
{
case -1: //ERROR
perror("Could not fork.\n");
break;
case 0: //CHILD
//Accept string from client.
//Edit: Why am I getting an error here? says: Invalid argument.
if(n = recv(newsock, str, MAX, 0)) {
perror("Recv error at server side.\n");
exit(1);
}
str[n]='\0';
if (n <= 0) {
if (n < 0)
perror("recv");
done = 1;
}
printf("String=>%s<",str);
//Redirect socket to STDOUT & STDERR.
test = close(WRITE); assert(test==0);
test = dup(newsock); assert(test==WRITE);
test = close(ERROR); assert(test==0);
test = dup(newsock); assert(test==ERROR);
if (!done)
{
if (str==something)
{
//execute command
}
else {
//Fork and execvp the command
}
//Sends End of Transaction character.
ENDTHETRANS();
exit(0);
}
break;
default: //PARENT
//Parent keeps accepting further clients.
wait(&status);
if ((newsock= accept(s, (struct sockaddr *)&remote, &t)) == -1) {
perror("accept");
exit(1);
}
printf("Connected.\n");
done=1;
break;
}
} while (!done);
}
close(s);
}
Im relatively new to programming in general and from my understanding the client code is good except that when it recieves the text back from the server it only recieves the text in small bits (2 rows at a time). I have to keep pressing enter on client promt to get the rest of the input. I have tried so many things that by this point I dont even know what I am doing wrong anymore.
Firstly, in the server code, after it recieves the string from the client I have a printf("String=>%s<",str); that outputs the string. However when the server prints the output as String=>ls -l the < key at the end gets eaten up somehow. It shouldnt be doing that right?
Any help much appreciated. Please bare in mind that I am a beginner and have only used pipes as inter process communcation before. Now I wanna make my first unix socket program.
Thanks in advance.
The usual problem in cases such as this is not realizing that SOCK_STREAM sockets don't preserve message boundaries. So data sent with a send call might be split up and received in multiple recvs, or it might be coalesced and multiple sends end up in a single recv. Most importantly, when a kernel send buffer fills up, a send call might write partial data (sending only some of the requested data) and return a short return value. You need to test for this and resend the rest of the data.
Another problem that often shows up is issues with line endings (particularly when talking between linux and windows). There may be extra carriage return characters (\r) in the either the client or server that confuse the other side. These tend to result in apparently missing or truncated output when printed.
edit
The line
if(t=recv(s, str, MAX, 0)<0)
is equivalent to
if(t = (recv(s, str, MAX, 0)<0))
that is, it sets t to 0 or 1 depending on whether there was an error or not. As with most errors of this type, turning on warnings will give you some indication about it.

select() not responding?

The objective of my program is to use select to manage multiple sockets. However, I thought of trying it with one socket first. Now, the problem that I am facing is that initially client sends data to server, and server receives it and displays it, but then when client again sends some data, the server code remains still at select command.
here are some snippets that will give you an idea of how I am initializing the socket.
if((master_socket = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
exit(1);
}
if((bind(master_socket, (struct sockaddr *)&req, sizeof(req))) < 0)
{
exit(1);
}
listen(master_socket, 5);
FD_SET(master_socket,&listening);
/* wait for connection, then receive and print text */
len = sizeof(struct sockaddr);
while(1)
{
FD_ZERO(&listening); //Flush out everything in socket
FD_SET(master_socket,&listening); // Add master
if(f_client>0) // Add client if any
{
FD_SET(f_client,&listening);
}
printf("Checking for new connection \n");
//Timeout is null, so waiting indefinitely
rc = select(FD_SETSIZE, &listening, NULL, NULL, NULL);
if (FD_ISSET(master_socket, &listening))
{
printf("Master side invoked\n");
if((f_client = accept(master_socket, (struct sockaddr *)&req, &len)) < 0)
{
exit(1);
}
}
else if (FD_ISSET(f_client,&listening))
{
if ((valread = read( f_client , buf, 1024)) == 0)
{
close(f_client);
f_client=0;
}
else
{
fputs(buf, stdout);
}
}
}
Basically in above program, it connects to the server, maintains a file descriptor for client f_client and add it. And in every round, it clears the socket, add master socket, and client socket if any, and then checks. Problem here is, first time it works, but second time when client sends some data. it gets hang to rc = select(FD_SETSIZE, &listening, NULL, NULL, NULL);
I am not to understand what is wrong here. Can anyone help?
if ((valread = read( f_client , buf, 1024)) == 0)
{
close(f_client);
f_client=0;
}
else
{
fputs(buf, stdout);
}
This code is broken. The fputs function can only be used with a C-style string. You just have arbitrary data with no particular structure. Since you ignore valread, you also have no idea how many bytes you read. (Think about it, how could fputs possibly know how many bytes to output? That information is only in valread, and you don't pass it that information.)
You've already received the data, this broken code just threw it away. If you log valread, you'll see that you actually already read it in your last call to read before the call to select that hung.
instead of fputs, you could use something like this:
for (int i = 0; i < valread; ++i)
putchar(buf[i]);

C programming socket buffer

Re: this client<->server (foodrequest-foodinfo scenario) I am trying to send receive to a successful client-server connection sock_fd. In this loop, I receive the first information back but the next iteration stops at the keyboard input ie readInFood(). Is there anything wrong with the way I am handling the buffer? or otherwise.
RESPONSE_BUFFER = 2200;
INPUT_BUFFER = 100;
int numbytes;
char foodType[INPUT_BUFFER];
char foodResponse[RESPONSE_BUFFER];
do {
//send a message to server
if (send(sock_fd, readInFood(foodType), INPUT_BUFFER, 0) == -1)
perror("send");
//receive the message
if ((numbytes = read(sock_fd, foodResponse, RESPONSE_BUFFER)) == -1) {
perror("receive");
exit(EXIT_FAILURE);
}
//end the buffer string
foodResponse[numbytes] = '\0';
//print the buffer
printf("\nThis is the information you require: %s", foodResponse);
} while (foodType[0] != 'q' || foodType[0] != 'Q');
My guess is that your socket is blocking because it expects more information or its not getting anything else. In that case perror() will not fire, but your program will continue to wait for info.

In my server cod that the child process created is terminating abnormally without doing its job

This server can handle 2 types of clients one which request one shot data transmission and another requested periodic data transmission.
It wait for control character from client to start and stop transmission.
For one shot 'c' start transmission and for periodic 'a' starts and 'b' stops it.
But as the execution comes to condition checking for 'a' the execution is halted there and child starts receiving unpredictable value like (0,32767).
When i checked with gdb than it also not showing any thing as come to "if(control=='a')".
Can u suggest me some thing to fix this problem.
`while(1)
{
sin_size = sizeof(struct sockaddr_storage);
connected = accept(sock1, (struct sockaddr *)&client_addr,&sin_size);
//connecteds[count]=connected;
//clients[count]=client_addr;
if(connected == -1){
perror("accept");
continue;
}
count++;
printf("\n%d %d\n",count,connected);
inet_ntop(client_addr.ss_family,get_in_addr((struct sockaddr *)&client_addr),s, sizeof s);
printf("server: got connection from %s\n", s);
pid=fork();
if(pid<0)perror("error in fork");
if(pid==0)
{
while(1){
int no;
char control;
printf("\n waiting for data request from clients:.......\n");
fflush(stdout);
bzero(&control,1);
while(1){
bytes_recieved = recv(connected,&control,1,0);
if(control=='a'||control=='b'||control=='c')
break;
}
r1.control1=control;
r1.client=client_addr;
send(sock,&r1,sizeof(struct recieved),0);
printf("\nreceived data request is :%c from client (%s)\n", control,s);
fflush(stdout);
if(control=='a')
{printf("..................");
struct argument *argu;
argu->dis=connected;
argu->sock=sock;
argu->cli=client_addr;
//inet_ntop(client_addr.ss_family,get_in_addr((struct sockaddr *)&client),s, sizeof s);
printf("transmission started for client:%s\n",s);
fflush(stdout);
pthread_create(&tid1,NULL,sends,(void*)argu);
pthread_create(&tid2,NULL,recieve,(void*)argu);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
control=value;
printf("comming here\n");
fflush(stdout);
}
if(control=='b')
{
printf("terminating the connection with client (%s).\n",s);
fflush(stdout);
break;
}
if(control=='c')
{
while(1){
recv(sock,&data1,sizeof(struct dataset),0);
if(data1.data==200)
break;
}
send(connected,&data1,sizeof(struct dataset),0);
printf("getting data from server %c\n%d\nterminating the connection with client (%s).\n",data1.a,data1.data,s);
fflush(stdout);
break;
}
}//end of while2
}//end of child
`
You do not allocate memory for the argu pointer.
struct argument *argu = malloc(sizeof(struct argument));
Remember to free the pointer after the two calls to pthread_join.
Edit
Better yet, instead of using a pointer, just use the structure:
struct argument argu;
argu.dis = connected;
/* etc. */
pthread_create(&tid1,NULL,sends,&argu);
pthread_create(&tid2,NULL,recieve,&argu);

Resources