Thread: Sending strings over socket

  1. #1
    Registered User
    Join Date
    Jan 2017
    Posts
    6

    Sending strings over socket

    Hello guys!

    I'm trying to send a string value from client to server. Basically, the client will send any string and the server will reply with Hello + any string you input.

    The thing is that after I'm reading the string from keyboard, the client doesn't go further to the next line.After I force quit the client, on the server will appear information regarding the message. I think I'm doing something wrong when reading the string as I made a test and the below cout doesn't print the string value.Please see the below:

    Code:
        answer.empty();
        input.empty();
    
    
        cout<<"[client]Enter your name: ";
        
        getline(cin, input);
        cout<<input; //doesn't reach this
    
    
        if(n = (send(sd, input.data(), input.size(), 0))<0)
        {
            perror("[client]Write() error to server.\n");
            return errno;
        }
    Also tried as below + directly with cin, same thing happens:

    Code:
    getline(cin, input,'\n');
    Last edited by danielleinad; 01-13-2017 at 06:47 AM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Since a simple program works, you're going to have to come up with an actual example which fails that we can test ourselves.
    Code:
    $ cat foo.cpp
    #include <iostream>
    #include <string>
    #include <iomanip>
    using namespace std;
    
    int main(void)
    {
      string input;
      getline(cin, input);
      cout << input << endl;
      cout << "ptr=" << input.data() << ", size=" << input.size() << endl;
      return 0;
    }
    $ g++ -Wall foo.cpp
    $ ./a.out 
    hello world
    hello world
    ptr=hello world, size=11
    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 2017
    Posts
    6
    Hello Salem, thank you for your reply.

    Server code: [C++] #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #inclu - Pastebin.com
    Client code: [C++] #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #inclu - Pastebin.com

    There are some things that are missing, the point is that I don't understand why cout is not working and when i force quit the client ctrl+c the information will flow on server

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Well you could add more debug code,
    Code:
    ///// client
    	cout<<"[client]Input your name: "<<flush;
    	getline(std::cin, input);
    	cout<<input;
    	if(n = (send(sd, input.data(), input.size(), 0))<0)
    	{
    		perror("[client]Write to server error.\n");
    		return errno;
    	}
    	cout << "Sent a message, wait for reply" << endl;
    ///// server
                while((n=recv(client, buf, sizeof(buf), 0))>0)
                {
                    msg.append(buf, buf+n);
                    cout << "Current msg=" << msg << endl;
                }
    Or use a debugger.
    Code:
    $ g++ -g -o client foo.cpp
    $ gdb -q client 
    Reading symbols from client...done.
    (gdb) run 127.0.0.1 7777
    Starting program: /home/sc/Documents/client 127.0.0.1 7777
    [client]Input your name: yo dude
    yo dude
    Sent a message, wait for reply
    ^C
    Program received signal SIGINT, Interrupt.
    0x00007ffff757d66d in __libc_recv (fd=3, buf=0x7fffffffdbe0, n=500, flags=0)
        at ../sysdeps/unix/sysv/linux/x86_64/recv.c:28
    28	../sysdeps/unix/sysv/linux/x86_64/recv.c: No such file or directory.
    (gdb) bt
    #0  0x00007ffff757d66d in __libc_recv (fd=3, buf=0x7fffffffdbe0, n=500, flags=0)
        at ../sysdeps/unix/sysv/linux/x86_64/recv.c:28
    #1  0x00000000004015d3 in main (argc=3, argv=0x7fffffffded8) at foo.cpp:69
    (gdb) up
    #1  0x00000000004015d3 in main (argc=3, argv=0x7fffffffded8) at foo.cpp:69
    69		while((n = recv(sd, buf, sizeof(buf), 0))>0)
    (gdb)
    Code:
    $ g++ -g -o server main.cpp
    $ gdb -q ./server
    Reading symbols from ./server...done.
    (gdb) set follow-fork-mode child
    (gdb) run
    Starting program: /home/sc/Documents/server 
    [server-15525]Waiting at the port 7777
    [server-15525]The client connected: 127.0.0.1:51302
    [New process 15533]
    [server-15533]Waiting a message...
    Current msg=yo dude
    ^C
    Thread 2.1 "server" received signal SIGINT, Interrupt.
    [Switching to process 15533]
    0x00007ffff757d66d in __libc_recv (fd=4, buf=0x7fffffffd9f0, n=1024, flags=0)
        at ../sysdeps/unix/sysv/linux/x86_64/recv.c:28
    28	../sysdeps/unix/sysv/linux/x86_64/recv.c: No such file or directory.
    (gdb) bt
    #0  0x00007ffff757d66d in __libc_recv (fd=4, buf=0x7fffffffd9f0, n=1024, flags=0)
        at ../sysdeps/unix/sysv/linux/x86_64/recv.c:28
    #1  0x0000000000401b20 in main () at main.cpp:108
    (gdb) up
    #1  0x0000000000401b20 in main () at main.cpp:108
    108	            while((n=recv(client, buf, sizeof(buf), 0))>0)
    (gdb)
    You can clearly see that the server prints out
    Current msg=yo dude
    and that the client reaches it's own recv() call to read the response.

    The problem (for you) is that the exit condition for the recv() loop on the server is the connection being CLOSED!

    What you need to do is send a delimiter (say \n) with each message, so that you can construct a recv/send loop in the server which sends back a message for each line received.

    > if(n = (send(sd, input.data(), input.size(), 0))<0)
    Watch where you're putting the parentheses here.
    You're NOT setting n to be the number of bytes sent, which is then compared with zero.
    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 2017
    Posts
    6
    oh, thank you, it works a little better. Although I'm failing to understand how should I send that delimiter (\n) after each message. I've appended to my message (+'\n') and on the server will receive an empty string I assume and the reply will be just Hello. Can you please advise what am I doing wrong?

  6. #6
    Registered User
    Join Date
    Jan 2017
    Posts
    6
    Anyway, I think I will send the size of the string first and then the message in order to make sure I read a limited amount of characters

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Either approach would work.
    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.

  8. #8
    Registered User
    Join Date
    Jan 2017
    Posts
    6
    So now everything is working as expected Thank you very much Salem, you are a true hero

    I have one more curiosity, though:

    Code:
    while(n<messageLength && (n=recv(client, buf, messageLength, 0))>0)
                {
                    msg.append(buf, n);
                    cout<<n;
                }
    Why is this working? Let's say messageLength is 6, if I would use "<=" everything would crash. In the parenthesis, it's evaluating the left side, when n is 5 and then in the right side n becomes 6 so that msg receives the correct value? I cannot find other explanation.

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    The thing to remember about SOCK_STREAM connections is that you sacrifice message boundaries for reliability.

    So if you do send("hello"), the transport mechanism is allowed to deliver you
    "hello"
    "he" followed by "llo"
    "hell" followed by "o"
    "h" "e" "l" "l" "o"

    Assuming buf is always large enough for any single message, you would typically do something like
    Code:
    int total = 0;
    while(total<messageLength && (n=recv(client, buf, messageLength-total, 0))>0 ) {
      // do things with n chars in buf
      total += n;
    }
    Or if you prefer
    Code:
    int remainder = messageLength;
    while ( remainder > 0 && (n=recv(client, buf, remainder, 0))>0 ) {
      // do things with n chars in buf
      remainder -= n;
    }
    How did you send the length? Is that vulnerable to message fragmentation?
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Sending Integer Via C Socket
    By SimplySud in forum C Programming
    Replies: 5
    Last Post: 12-24-2014, 09:23 AM
  2. sending matrix over UDP socket
    By n.a.s in forum C Programming
    Replies: 3
    Last Post: 05-21-2014, 10:33 AM
  3. Socket Overflow by sending / receiving ACK's
    By MaSSaSLaYeR in forum C Programming
    Replies: 13
    Last Post: 11-24-2011, 02:38 AM
  4. sending in socket
    By fairyjerry14 in forum C Programming
    Replies: 4
    Last Post: 10-08-2007, 07:11 AM
  5. sending zero bytes over TCP socket
    By nantonop in forum Networking/Device Communication
    Replies: 4
    Last Post: 09-03-2007, 08:10 AM

Tags for this Thread