ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
The send() and recv() are used multiple times to communicate two machines. But it only works for the first time. After that the data returned from recv() remains the same.
Here are parts of the codes.
Could be multiple things...I usually start by printing out the buffers right before I send it and right after I receive it to make sure they are the same. Print out the length of the buffer to make sure it is the same value you are passing send.
how do you define commands[] or rather what type is it?
Try shutdown(sd, SHUT_RDWR); instead of close(sd); and see what happens. Also, it could be in the server code.
ta0kira
PS If the server reads until EOF, it might be blocking waiting for the socket to be shut down (close doesn't actually destroy the connection); therefore it might not actually get back to the accept call.
Sorry I am not sure the shutdown command is needed here...I have never closed a socket any other way than close(socket_fd).
Since the full code isn't given it is hard to say but maybe the loop isn't incrementing the pointer/variable. Maybe the memory in the buffers aren't being handled correctly. But since you say that at least the first command transfers correctly that your sockets might not be the problem. For debugging just put in a lot of printf statement or use gdb to debug. If you feel the issues are with socket programming either google "Beej's guide to network programming" or check out a copy of the steven's unix network programming book from the library. If you think the network or sockets are not actually sending the packets then wireshark could be your best friend for debugging such an issues.
I agree with j-osh. Without seeing the full code, it is hard to determine where the problem lies.
@ Jane2008 -
How have you declared 'buffer'? Are you initializing it with nulls before using it?
With respect to your socket, is it setup as non-blocking?
Be aware that when a message is sent via a TCP socket, it is possible that the message may not arrive in one packet; it may be provided in multiple packets, depending on the size of the message.
How do you determine that you have received a complete message? Are the messages newline-terminated, or does it consist of a fixed-length of data? If you are expecting lots of individual messages, you may need to perform I/O buffering of the data that is received, and then pluck out individual messages, when say, a newline is detected.
You are right, except of course when the data expected is a string. It's nice to have a null terminated buffer. Of course one can manually add a null to terminate the buffer after the data has been received.
Initializing the buffer to all nulls, as I have shown in my example, was not a big effort. In fact, it is wise to always initialize variables (when they are declared).
Thanks. Here are the full codes.
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
extern int errno;
extern int h_errno;
int main(int argc, char **argv)
{
int port = 8080;
struct protoent *protocol;
int rval;
int sd;
struct sockaddr_in socketaddr;
char *ptr ="192.168.0.100";
char *message = "$U";
char *commands[]={"\0", "$U", "$T", "%U", "%T", "#U", "#T", "#F","#D", "#S"};
// Initialize the buffer but seems no use, the data in buffer remains same
char response[1024]={0};
int choice;
/* Choose what protocol is used */
protocol = getprotobyname( "tcp" );
if ( !protocol )
{
perror( "getprotobyname()" );
return (errno);
}
printf("TCP is supportable!\n");
/* Create socket */
sd = socket( PF_INET, SOCK_STREAM, protocol->p_proto );
if ( sd == -1 )
{
perror( "socket()" );
return (errno);
}
printf("The socket is created successfully.\n");
/* Setup info about the remote host*/
memset( &socketaddr, 0, sizeof(socketaddr) );
/* Connect to the host*/
rval = connect( sd, (struct sockaddr *) &socketaddr, sizeof(socketaddr) );
if ( rval == -1 )
{
perror( "connect()" );
return (errno);
}
printf("Connect successfully!\n");
/* Now that we're connected, we can send and receive all we want.
* I've decided to use this example as a means of simply grabbing
* whatever banner the server sends us and sending it to stdout.
*/
printf("Please choose the operation:\n");
printf("1. Read voltage configuration\n");
printf("2. Read temperature & fan configuration\n");
printf("3. Write voltage configuration\n");
printf("4. Write temperature & fan configuration\n");
printf("5. Read voltage data\n");
printf("6. Read temperature data\n");
printf("7. Read fan revolution data\n");
printf("8. Read switch status\n");
printf("9. Read system monitor status\n");
printf("0. Exit\n");
I tested your client application with my server application. The only modifications I did to your app was to change the port number, the IP address, and I inserted a '\n' character at the end of each of the command strings. The latter modification was to satisfy my server's message protocol requirements.
Anyhow, your application worked, albeit my server was sending back a small message (the number of characters received).
Because you have stated that your client application is not working as expected, I would recommend that you look into two areas:
1. Ensure that your client app has the correct message protocol to talk to the server (i.e. check your command strings).
2. Check that the server is receiving your client's messages correctly, and is responding correctly.
P.S. Your client application outputs the same string ("The temperature is: ...", regardless of the choice selected. For example:
Code:
...
7. Read fan revolution data
8. Read switch status
9. Read system monitor status
0. Exit
1
$U
The temperature is: Msg of 3 bytes received.
2
$T
The temperature is: Msg of 3 bytes received.
3
%U
The temperature is: Msg of 3 bytes received.
4
%T
The temperature is: Msg of 3 bytes received.
5
#U
The temperature is: Msg of 3 bytes received.
6
#T
The temperature is: Msg of 3 bytes received.
7
#F
The temperature is: Msg of 3 bytes received.
8
#D
The temperature is: Msg of 3 bytes received.
9
#S
The temperature is: Msg of 3 bytes received.
Thanks. The protocol is OK otherwise I will not receive data from it and the server can receive client's messages correctly. If 1 is entered first, the volt data is received. If 2 is entered first, the corresponding data is received. ...
But the problem is when entered 2(or other) after 1, the returned data is volt data.
Do you noticed that whatever option you entered, the buffer returns the same message "Msg of 3 bytes received". I think the data in your buffer is still same.
Because you have stated that your client application is not working as expected, I would recommend that you look into two areas:
1. Ensure that your client app has the correct message protocol to talk to the server (i.e. check your command strings).
2. Check that the server is receiving your client's messages correctly, and is responding correctly.
P.S. Your client application outputs the same string ("The temperature is: ...", regardless of the choice selected. For example:
Code:
...
1
$U
The temperature is: Msg of 3 bytes received.
2
$T
The temperature is: Msg of 3 bytes received.
3
%U
The temperature is: Msg of 3 bytes received.
4
%T
The temperature is: Msg of 3 bytes received.
5
#U
The temperature is: Msg of 3 bytes received.
6
#T
The temperature is: Msg of 3 bytes received.
7
#F
The temperature is: Msg of 3 bytes received.
8
#D
The temperature is: Msg of 3 bytes received.
9
#S
The temperature is: Msg of 3 bytes received.
Thanks. The protocol is OK otherwise I will not receive data from it and the server can receive client's messages correctly. If 1 is entered first, the volt data is received. If 2 is entered first, the corresponding data is received. ...
But the problem is when entered 2(or other) after 1, the returned data is volt data.
Do you noticed that whatever option you entered, the buffer returns the same message "Msg of 3 bytes received". I think the data in your buffer is still same.
Quote:
Originally Posted by Jane2008
Because you have stated that your client application is not working as expected, I would recommend that you look into two areas:
1. Ensure that your client app has the correct message protocol to talk to the server (i.e. check your command strings).
2. Check that the server is receiving your client's messages correctly, and is responding correctly.
P.S. Your client application outputs the same string ("The temperature is: ...", regardless of the choice selected. For example:
Code:
...
1
$U
The temperature is: Msg of 3 bytes received.
2
$T
The temperature is: Msg of 3 bytes received.
3
%U
The temperature is: Msg of 3 bytes received.
4
%T
The temperature is: Msg of 3 bytes received.
5
#U
The temperature is: Msg of 3 bytes received.
6
#T
The temperature is: Msg of 3 bytes received.
7
#F
The temperature is: Msg of 3 bytes received.
8
#D
The temperature is: Msg of 3 bytes received.
9
#S
The temperature is: Msg of 3 bytes received.
Pay no attention to the output I provided earlier; my server responds back with the same response everytime and includes the number of bytes received, which was 3 (e.g. "#U\n");
Here's the output when I modified my server to echo the string that was sent to it. Note that I removed the '\n' characters from the printf() statements from your client application so that I would not output two newlines.
Code:
$ ./a.out
TCP is supportable!
The socket is created successfully.
Connect successfully!
Please choose the operation:
1. Read voltage configuration
2. Read temperature & fan configuration
3. Write voltage configuration
4. Write temperature & fan configuration
5. Read voltage data
6. Read temperature data
7. Read fan revolution data
8. Read switch status
9. Read system monitor status
0. Exit
1
$U
The temperature is: Server received: $U
2
$T
The temperature is: Server received: $T
3
%U
The temperature is: Server received: %U
4
%T
The temperature is: Server received: %T
5
#U
The temperature is: Server received: #U
6
#T
The temperature is: Server received: #T
7
#F
The temperature is: Server received: #F
8
#D
The temperature is: Server received: #D
9
#S
The temperature is: Server received: #S
10
$
Anyhow, I'm certain the problematic issues with your client application are because of one or more of the following:
1) The client application is not following the correct messaging protocol, or
2) The server is not handling the incoming messages as expected, or
3) The server is not responding properly.
Please examine each of the possibilities above before you think of anything else!
Last edited by dwhitney67; 02-11-2009 at 12:52 PM.
Thanks.
I found that the client application only supports one time communication. That is, once connected, only one send and recv can be used to get the message. After that, you have to connect again.
I modified the codes as follows. First choose the option, then connect, send, recv, close finally. But the close() and shutdown() doesn't work.
char* io_operation(char* commands)
{
int rval;
int sd;
struct sockaddr_in socketaddr;
struct protoent *protocol;
int port = 8080;
char *ptr ="192.168.0.100";
static char response[1024];
/* Choose what protocol is used */
protocol = getprotobyname( "tcp" );
if ( !protocol )
{
perror( "getprotobyname()" );
// return (errno);
}
/* Connect to the host*/
rval = connect( sd, (struct sockaddr *) &socketaddr, sizeof(socketaddr) );
if ( rval == -1 )
{
perror( "connect()" );
// return (errno);
}
/* Now that we're connected, we can send and receive all we want.
* I've decided to use this example as a means of simply grabbing
* whatever banner the server sends us and sending it to stdout.
*/
/* Send the commands to the module */
rval = send(sd, commands, strlen(commands), 0);
if( rval == -1)
{
perror("send()");
// return(errno);
}
/* Receive messages sent from module */
rval = recv( sd, response, sizeof(response), 0 );
if ( rval == -1 )
{
perror( "recv()" );
// return(errno);
}
else
{
printf("%s\n",response);
}
/* Shut down the socket */
close( sd );
shutdown(sd, SHUT_RDWR);
return response;
}
int main(int argc, char **argv)
{
int choice;
char commands[1024]={0};
char response[1024]={0};
char strcommand[100]={0};
/* Print the operation option */
printf("Please choose the operation:\n");
printf("1. Read voltage configuration\n");
printf("2. Read temperature & fan configuration\n");
printf("3. Write voltage configuration\n");
printf("4. Write temperature & fan configuration\n");
printf("5. Read voltage data\n");
printf("6. Read temperature data\n");
printf("7. Read fan revolution data\n");
printf("8. Read switch status\n");
printf("9. Read system monitor status\n");
printf("0. Exit\n");
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.