Thread: help with socket send/recv

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    89

    help with socket send/recv

    This is my first attempt playing with sockets and I am just working with some sample code that I got to compile. For some reason however this loop in my code hangs after the first execution. Any ideas why?

    Code:
    while (recv(theSocket, szBuf, 255, 0) > 0) {
          cout << "  --  " << szBuf << "\n";
    
          memset(szBuf, 0x0, 255);  // set line to all zeroes
          strcpy(szBuf, "fmstdnt2");
          cerr << "Sent: " << szBuf << " to server.\n";  
    
          // Send converted line back to client.
          if (send(theSocket, szBuf, strlen(szBuf), 0) < 0)
            cerr << "Error: cannot send modified data";
    
          memset(szBuf, 0x0, 255);  // set line to all zeroes
          cerr << "Zeroed buffer.\n";
        }
     cout << "Exited loop!\n";
    this is the output I get:

    Code:
    Stream Client connecting to server: xxx.xxx.xxx.xxx on port: 23
      --   ²$
    Sent: fmstdnt2 to server.
    Zeroed buffer.

  2. #2
    Registered User
    Join Date
    May 2006
    Posts
    89
    Also I was wondering... connecting to Telnet like that I got those two garbage chars "*$". Are these really just garbage or are they useful info from the server? If so how can I see that? I kind of think I need to use some kind of emuation like VT100 VT120 or VT320 but I will worry about that later. My goal right now is to just get my program to log into a server by sending a name and password at the appropriate times.
    thanks

    EDIT: I have found somewhere that recv() is a blocking(?) process, meaning it waits for data before continuing. Is this true? If so that explains my loop issue... Does anyone know how to coax more ouput from a telnet server? I just want to get as far as logging in but it doesnt send any login prompt.
    Last edited by ac251404; 06-27-2006 at 02:28 PM.

  3. #3
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    The server can send some binary commands to negociate stuff like terminal type, echoing, etc. Read the RFC on the telnet protocol. Google things like "telnet protocol", etc. (Here's one such page that might help.)

    And yes, both recv()/send() will block. recv() will block until data arrives, the socket is closed, or there's an error. You have to design around this. You can set the socket to non-blocking - if you do, recv()/send() will return an error code (EWOULDBLOCK) if they would block normally. The other option is to use select()/poll() which will tell you if the socket can be read.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  4. #4
    Registered User
    Join Date
    May 2006
    Posts
    89
    okay well I read thru that guide and another I found on google. I understand how commands are seen by the server and sent to the client. I tried converting the two garbage chars I got to an int to see what the server was sending and got 0 which seems to associate with NULL which I supposed makes sense. The new problem however is how to actually send the commands. Do I send them in their decimal form or there ascii form? Ex:

    Client 255(IAC),251(WILL),24
    Server 255(IAC),253(DO),24
    Server 255(IAC),250(SB),24,1,255(IAC),240(SE)
    Client 255(IAC),250(SB),24,0,'V','T','2','2','0',255(IAC) ,240(SE)

    was given as a sample telnet session. Do I send an actual string such as "255(IAC)" or "IAC" or "255" ? None of the protocol pages specify this and i am unable to test it because every time i try to connect to a server to play around with stuff it automatically uses the built in telnet protocol to handle everything.

    thanks

  5. #5
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    Send the binary representation of the numbers. So for 255(IAC),251(WILL),24, send 0xFF,0xFB,0x18.

    Programs like Ethereal are wonderful for jobs like this: Ethereal lets you capture network traffic and view it, allowing you to see what your program is actually sending, or what some other network program is actually sending. So, you could start a capture with Ethereal, connect Putty (and excellent Telnet/SSH client) to some public telnet server, and see what gets send back and forth.

    Also, if you're having trouble converting... what datatype are you storing the data in? If you're using char's, then some of the values might appear negative, if char's range is -128 - 127.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  6. #6
    Registered User
    Join Date
    May 2006
    Posts
    89
    i am storing my stuff in a character array. char buf[256]
    So can I just run a char_to_bin type function for each character or command and send that way?

    I am gonna look at Ethereal if I can find it. Sounds like EXACTLY what I have been needing.
    Thanks!

    update - Ok great I can see all the info I need being sent back and forth... new problem. the send() function works with const *char but sending character arrays obviously does not work. Do I need to send in a different manner so that the server recieves binary or does send handle this on its own? If so I think I am back to where I started.
    Last edited by ac251404; 06-28-2006 at 01:57 PM.

  7. #7
    I am me, who else?
    Join Date
    Oct 2002
    Posts
    250
    Honestly, most things should be able to communicate via ascii just fine, especially telnet.

    Ethereal is a good program, but really, making a telnet connection is not nearly as hard as things are seeming. I would really advise making it a bit more robust and using select as opposed to blocking on the socket. You won't get the interactivity you want out of such an app. select() will take a few more minutes to learn but it will make things a lot easier for you in the end. It will allow you to select when something has data, otherwise you can do other stuff in the background and make a less frustrating program. In this case at least.

  8. #8
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    Quote Originally Posted by ac251404
    update - Ok great I can see all the info I need being sent back and forth... new problem. the send() function works with const *char but sending character arrays obviously does not work. Do I need to send in a different manner so that the server recieves binary or does send handle this on its own?
    send() sends raw data - it doesn't care about characters, etc. It's declared as*:
    Code:
    int send(int s, const void *msg, size_t len, int flags);
    , passing a char array like you're doing is perfectly acceptable.

    The one thing that bites most people in the butt is that send() might not send everything you ask it to send. It's imperative that the return value is checked: On success, send() will tell you how much it really sent. For simple blocking socket applications, you can easily write a function that ensures everything is sent:
    Code:
    int sendall(int s, void *msg, int len)
    {
       int transferred = 0, send_ret;
       unsigned char *umsg = msg;
    
       while(transferred < len)
       {
          send_ret = send(s, umsg + transferred, len - transferred, 0);
          if(send_ret <= 0) return send_ret;
          transferred += send_ret;
       }
       return len;
    }
    For raw binary, I usually use unsigned char - 1 byte & unsigned (or whatever type is). So:
    Code:
    unsigned raw_data[3] = {0xFF, 0xFB, 0x18};
    sendall(your_socket, raw_data, 3);
    Should hopefully work. There's more than one way to accomplish this however.
    EDIT:
    A better way to work that might even be {IAC, WILL, 0x18};
    where IAC & WILL are either:
    #define IAC 0xFF
    const unsigned char IAC 0xFF;
    Last edited by Cactus_Hugger; 06-28-2006 at 07:32 PM.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  9. #9
    Registered User
    Join Date
    May 2006
    Posts
    89
    OK I am trying what you gave me but the compiler is giving me this:

    invalid conversion from `void*' to `unsigned char*'

    for this line:
    Code:
       unsigned char *umsg = msg;
    and

    invalid conversion from `unsigned char*' to `const char*'
    here
    Code:
    send_ret = send(s, umsg + transferred, len - transferred, 0);
    edit: still didnt get the sendall function working but I finally got the client/server talking. My real problem was trying to send things like IAC, DO, WILL etc as strings/char arrays when they should have been sent as their corresponding ascii codes. still have a long way to go but making progress.

    dpro: I do plan on eventually making my program non-blocking but my goal right now is to just send something to the server and recieve some real output back.
    Last edited by ac251404; 06-29-2006 at 11:44 AM.

  10. #10
    Registered User
    Join Date
    May 2006
    Posts
    89
    okay i'm not doing to bad using Ethereal as a reference and figuring out my command structure. I have written a function which takes regular string like commands and converts them to the appropriate character and sends them. i.e. "IAC DO ECHO" is converted to 0xff 0xfd 0x01 and put into a character array and sent via send(). Works like a charm. Only problem is when I am trying to negotiate terminal type it cuts off my command early. Here is the line from Ethereal:
    Code:
                                               HEX
    Suboption Begin: Terminal Type           ff fa 18 
        Here's my terminal type              00        <-------------- problem line
        Value: vt220                         76 74 32 32 30 
    Command: Suboption End                   ff  f0
    That is taken from a normal telnet session. My problem is that when I try to send the exact same thing from my program it stops reading at the 00 line. If i replace 00 with anything it doesnt recognize it as a valid command.
    Any ideas?
    thanks

  11. #11
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    Sry - sendall() is a C function. The first warning will show in C++. The second warning comes from the definition of send(), which isn't actually what I said it to be earlier. I'm assuming that you're on Windows... windows has the strange idea that the second argument to send() is a const char *... hence the warning.

    As for the "stops reading at the 00 line" -> if you're saying that the size of your buffer is strlen(buffer) in send(), then yes, this will happen. strlen() will interpret whatever you pass to it as a C string, which, since you're sending binary data, it isn't. (Remember: C strings are terminated with 0x00.) It sees the 00 and thinks your buffer ends there, when it really doesn't. You'll have to keep track of the real size of your buffer by some alternative means.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. socket programming question, closing sockets...
    By ursula in forum Networking/Device Communication
    Replies: 2
    Last Post: 05-31-2009, 05:17 PM
  2. socket programming in linux
    By crazeinc in forum C Programming
    Replies: 1
    Last Post: 05-27-2005, 07:40 PM
  3. when to close a socket
    By Wisefool in forum Networking/Device Communication
    Replies: 5
    Last Post: 11-02-2003, 10:33 AM
  4. problem closing socket
    By Wisefool in forum Networking/Device Communication
    Replies: 2
    Last Post: 10-29-2003, 12:19 PM
  5. socket newbie, losing a few chars from server to client
    By registering in forum Linux Programming
    Replies: 2
    Last Post: 06-07-2003, 11:48 AM