Thread: Server recv data problem! Please help!

  1. #1
    Registered User
    Join Date
    Jan 2005
    Posts
    30

    Unhappy Server recv data problem! Please help!

    Hello All!
    I have a problem and I realy need help! I want to make my simple server recognize commands! The problem is that when I recive data from client I get garbage at the end of the data. For example I connect with telnet to my server and send message:
    This is the first message
    Server displays them like this:
    This is the first message öÿ¿ ¨õÿ¿) @ @øÈõÿ¿
    I simply store all the recived data into array buffer and this is the result of:
    Code:
    cout << buffer << endl;
    I know that recv function returns size of the recived data, so I can make just a loop like this, to filter thous characters out:
    Code:
    for(int q=0; q<recv_data_size; q++){
        cout << buffer[q];
    }
    This will display me a data without thous garbage characters, but the problem for server to detect command!

    I have my buffer 100 bytes long, so I clear thous garbage characters like this:
    Code:
    for(int c=recv_data_size-2; c<array_size; c++){
        buffer[c] = '\0';
    }
    I used recv_data_size-2 so that the code allso would clear \n and \r characters!

    This will clean the garbage out and for example if I will send command from client stop, then my buffer will look like this:
    [s],[t],[o].[p],[\0],[\0]....
    The problem is that this code does't work:
    Code:
    if(buffer == "stop"){
       cout << "Command executed!\n";
    }
    Can you please show me how to make my server recognize commands?
    Here is the source code. I'm on Linux:

    Code:
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <iostream>
    
    #define port 1000
    #define conn 10
    #define buffsize 100
    
    
    using namespace std;
    
    int main(){
    
     	int sock_fd, fd;
     	struct sockaddr_in server;
     	struct sockaddr_in client;
    	
     	socklen_t sin_size;
    
    	char buffer[buffsize];
    	
    	server.sin_family = AF_INET;
            server.sin_port = htons(port);
    	server.sin_addr.s_addr=INADDR_ANY;
    	
    	if((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
     		perror("socket();");
     		exit(1);
    	}
    	
    	
    	if(bind(sock_fd,(struct sockaddr *)&server,sizeof(struct sockaddr)) == -1){
    		perror("bind();");
    		exit(1);
    	}
    	
    	
    	if(listen(sock_fd, conn) == -1){
    		perror("listen();");
    		exit(1);
    	}
    	
    	sin_size = sizeof(struct sockaddr_in);
    	
    	while(true){
    	
    		fd = accept(sock_fd,(struct sockaddr *)&client,&sin_size);
    		
    		while(true){
    		    int data_lenght =  recv(fd, buffer, sizeof(buffer), 0);
    		    
    		    for(int q=data_lenght-2; q<buffsize; q++){
    		           buffer[q] = '\0';
    		    }
    		    
    		    if(buffer == "command"){
    		        cout << "Command executed successfully!\n";
    		    }
    		    
    		}		
    	}
    	
    return 0;
    }
    Please help me!!! Thank you!
    Last edited by hyaku_; 01-07-2005 at 04:57 PM. Reason: Syntax error in code!

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > if(buffer == "command"){
    You might be writing C++, but these are still 'C' strings, so strcmp is in order

    if( strcmp(buffer,"command") == 0 ){
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    30
    Thank you very much! It works now!!!

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Since you only actually need one \0, you can do this

    Code:
        int data_lenght =  recv(fd, buffer, sizeof(buffer)-1, 0);  // allow for a \0
        if ( data_lenght > 0 ) buffer[data_lenght] = '\0';
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    30
    Thank you!!!
    On last question. When I run my server and the close it manualy with Ctrl + C or in code with shutdown(sock_fd, 0); exit(0); After I run it again I get this error:
    bind();: Address already in use
    I think I didn't close the socket right! How can I close it? Close(); works only for C

  6. #6
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Use close(sock_fd) on linux, or closesocket(sock_fd) on windows. shutdown() doesnt actually close the socket.

  7. #7
    Registered User
    Join Date
    Dec 2004
    Posts
    95
    The code you posted is broken in terms of working reliably under all network conditions. TCP/IP doesn't guarantee that a message such as "command" will be received in one recv call (because TCP/IP regards the data as a simple byte stream). You could receive "comm" from one call then "and" from the other, for example, or if the client is sending another command, the second call could contain some of that command.

    If you're testing over the loopback address, or a local network, you may not see this often, if ever, especially with small amounts of data, but on the internet you will.

    The point is that the socket doesn't care about your application protocol - it just sends and receives a stream of bytes. You must impose some sort of scheme yourself to determine where a message ends, or your code will break sooner or later.

    HTTP, for example, delimits messages with "\r\n\r\n", so even if a message is split, the receiver knows when the message ends.

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    30
    Thank you very much! I didn't know that!
    So when I receive my command the command will end with '\r\n' or with '\r\n\r\n'! Now I use telnet as a client! Thanx!

  9. #9
    Registered User
    Join Date
    Dec 2004
    Posts
    95
    No, that was just an example, you have to design your application protocol to delimit messages in some way. You could do what HTTP does, you could do it another way - it's up to you.

  10. #10
    Registered User
    Join Date
    Jan 2005
    Posts
    30
    Thank you!
    Well, I want to make a simple server that does something with parallel port, controls some device or something like that. Then I will use telnet to connect to my computer and control my device.

    For example if I send "something" by telnet, my server recv(); function returns 11. That means that telnet is sending two more bytes. I think its not '\n', because '\n' is 1 byte. I know that there allso exist something like line feed. What are thous 2 bytes?

    And I have read a little about IPv6. Do programms that are programmed for IPv6 will work with programms that use old IP protocol, and will IP addresses look different in IPv6? Thank you!

  11. #11
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    What are thous 2 bytes?
    Why don't you print them out and see for yourself?

    Do programms that are programmed for IPv6 will work with programms that use old IP protocol
    No, IPv6 is not backwards compatible to IPv4.

    and will IP addresses look different in IPv6?
    Yes, they look very different.

  12. #12
    Registered User
    Join Date
    Jan 2005
    Posts
    30
    Thanks!
    I allready printed them out, but last two bytes are blank. But when I print the whole text out with loop like this:
    Code:
    int recv_data_size = recv(...);
    for(int q=0; q<recv_data_size; q++){
        cout << buffer[q];
    }
    It prints out all the text including thous two bytes and put cursor in the new line!!!

  13. #13
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Well the bytes are probably \r\n, but to print them out you should do:
    Code:
    cout<< static_cast<int>(buffer[q]);
    instead of
    Code:
    cout << buffer[q];

  14. #14
    Registered User
    Join Date
    Jan 2005
    Posts
    2
    Quote Originally Posted by hyaku_
    I know that recv function returns size of the recived data, so I can make just a loop like this, to filter thous characters out:
    Code:
    for(int q=0; q<recv_data_size; q++){
        cout << buffer[q];
    }
    This will display me a data without thous garbage characters, but the problem for server to detect command!
    I have a similar issue. Is filtering out the garbage really an acceptable approach, or is it ignoring the actual problem? Is the garbage here a result of his coding or the nature of network programming?
    Last edited by kinktoy; 01-28-2005 at 01:24 PM.

  15. #15
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Welcome to the forums!

    In the future, if you have a problem, post a new thread and, if needed, provide a link back to an old thread that helps explain your problem.

    In this case, the garbage characters were not sent over the network. They were the random characters in the uninitialized array that were not written over. Because the network data was not nul terminated, the print function continued past the end of the data and printed garbage characters. When you receive network data, you must make sure it is nul terminated if you wish to work with it as a string.

    TCP is a reliable error corrected protocol and you will typically recieve the same data that was sent. However, the sender may send garbage, for accidental or malicious reasons.
    Code:
    /* Use -1 so room is left for the nul terminator. */
    int data_length = recv(sock, buffer, sizeof(buffer) - 1, 0);
    
    /* Explictly nul terminate the data before use. */
    if (data_length >= 0) buffer[data_length] = '\0';
    If you are having troubles, please post some code that demonstrates the problem. Please remember to use [code]code here[/code] tags.
    Last edited by anonytmouse; 01-28-2005 at 01:54 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. recv data with sockets
    By r063r in forum C++ Programming
    Replies: 2
    Last Post: 10-05-2008, 09:42 AM
  2. Sending data to a server
    By Hakins90 in forum Networking/Device Communication
    Replies: 6
    Last Post: 04-16-2008, 07:54 AM
  3. Bitmasking Problem
    By mike_g in forum C++ Programming
    Replies: 13
    Last Post: 11-08-2007, 12:24 AM
  4. recv() problem:(
    By piotrek_no_1 in forum Networking/Device Communication
    Replies: 5
    Last Post: 05-12-2005, 11:52 PM
  5. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM