tags:

views:

61

answers:

2

Hey guys, here is my code.

int main() { 

    char buffer[BUFSIZE]; 

    // define our address structure, stores our port
    // and our ip address, and the socket type, etc.. 
    struct sockaddr_in addrinfo; 
    addrinfo.sin_family = AF_INET; 
    addrinfo.sin_port = htons(PORT); 
    addrinfo.sin_addr.s_addr = INADDR_ANY; 


    // create our socket. 
    int sock; 
    if ( (sock = socket(addrinfo.sin_family, SOCK_STREAM, 0))  < 0) { 
        cout << "Error in creating the socket."; 
    } 

    // bind our socket to the actual adress we want 
    if (bind(sock, (struct sockaddr*)&addrinfo, sizeof(addrinfo)) != 0) { 
        cout << "Error in binding."; 
    } 

    // open the socket up for listening
    if (listen(sock, 5) != 0) { 
        cout << "Error in opening listener."; 
    } 
    cout << "Waiting for connections...." << endl; 

    char *msg = "Success! You are connected.\r\n"; 

    // continuously accept new connections.. but no multithreading.. yet
    while(1) { 

        struct sockaddr_in client_addr;
        socklen_t sin_size = sizeof(client_addr); 

        if(int client = accept(sock, (struct sockaddr*)&client_addr, &sin_size)) { 
            cout << "Recived new connection from " << inet_ntoa(client_addr.sin_addr) << endl; 
            send(client, msg, strlen(msg), 0); 
            while(1) { 
                send(client, buffer, recv(client, buffer, BUFSIZE, 0), 0);

                cout << buffer << endl; 
                strcpy(buffer, ""); 
            } 

        } else { 
            cout << "Error in accepting new connection." << endl; 
        } 

    } 

    close(sock); 
    return 0; 
} 

Now, I'm very new to sockets, Im just sort of trying to get a feel for them but I do have some experience with sockets in PHP. I'm using telnet via putty on my linux machine to test this, I don't know if thats causing any issues but the server is outputting some strange characters and I don't know why. I think it has something to do with the buffer, but I'm not really sure. I can send things like "hi" to the server via telnet and it outputs them just fine and sends them back to me but when I send things like "hoobla" it starts the funky character stuff. Any suggestions would be helpful!

Thanks in advance!

+1  A: 

The problem is that buffer is not guaranteed to contain a string-terminating null character. Add the line buffer[BUFSIZE-1] = '\0' just before your cout << buffer.

Even better, actually record how many bytes were received, and use that information to determine if you overran your buffer.

Borealid
hmm I understand what you're saying about the null character. But it doesn't seem to be working. I'm still getting strange character stuff for output. I surely wouldn't be overflowing my buffer var with a four letter string would I?
Dalton Conley
@Borealid, you need to use the return value from `recv` to store the nul byte, otherwise a recv of "hello" followed by another of "x" will give you "xello" (plus whatever garbage is _already_ in the buffer beyond the fifth byte (up to the end) in both cases).
paxdiablo
+7  A: 

You're getting rubbish printed out because recv does not null-terminate your buffer.

The important section in the below code is:

int num = recv(client,buffer,BUFSIZE,0);
if (num < 1) break;

send(client, ">> ", 3, 0);     // <<-- Nice to have.
send(client, buffer, num, 0);

buffer[num] = '\0';            // <<-- Really important bit!

if (buffer[num-1] == '\n')     // <<-- Nice to have.
    buffer[num-1] = '\0';      // <<-- Nice to have.

cout << buffer << endl;

which will properly terminate your buffer before trying to print it, as well as remove the trailing newline if present (and allow the client to distinguish between input and echoed lines).

This one (a complete program) works a little better:

using namespace std;
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>

#define BUFSIZE 1000
#define PORT 1234

int main() {
    char buffer[BUFSIZE];

    // define our address structure, stores our port
    // and our ip address, and the socket type, etc..
    struct sockaddr_in addrinfo;
    addrinfo.sin_family = AF_INET;
    addrinfo.sin_port = htons(PORT);
    addrinfo.sin_addr.s_addr = INADDR_ANY;

    // create our socket.
    int sock;
    if ( (sock = socket(addrinfo.sin_family, SOCK_STREAM, 0))  < 0) {
        cout << "Error in creating the socket.";
        return -1;
    }

    // bind our socket to the actual adress we want
    if (bind(sock, (struct sockaddr*)&addrinfo, sizeof(addrinfo)) != 0) {
        cout << "Error in binding.";
        return -1;
    }

    // open the socket up for listening
    if (listen(sock, 5) != 0) {
        cout << "Error in opening listener.";
        return -1;
    }

    char *msg = "Success! You are connected.\r\n";

    // continuously accept new connections.. but no multithreading.. yet
    while(1) {
        cout << "Waiting for connections...." << endl;

        struct sockaddr_in client_addr;
        socklen_t sin_size = sizeof(client_addr);

        if(int client =
            accept(sock, (struct sockaddr*)&client_addr, &sin_size))
        {
            cout << "Recieved new connection from "
                << inet_ntoa(client_addr.sin_addr) << endl;
            send(client, msg, strlen(msg), 0);
            while(1) {
                int num = recv(client,buffer,BUFSIZE,0);
                if (num < 1) break;
                send(client, ">> ", 3, 0);
                send(client, buffer, num, 0);

                buffer[num] = '\0';
                if (buffer[num-1] == '\n')
                    buffer[num-1] = '\0';
                cout << buffer << endl;
                strcpy(buffer, "");
            }
        } else {
            cout << "Error in accepting new connection." << endl;
        }
    }
    close(sock);
    return 0;
}

On the client side:

$ telnet 127.0.0.1 1234
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Success! You are connected.
hello
>> hello
my name is pax
>> my name is pax
and you?
>> and you?
<CTRL-D>
Connection closed by foreign host.

and, on the server side:

$ ./testprog
Waiting for connections....
Recived new connection from 127.0.0.1
hello
my name is pax
and you?
Waiting for connections....
paxdiablo
ok, so recv actually returns the byte size it contains?
Dalton Conley
Yes, or -1 on error or 0 if other end closes the connection, both of which the code treats equally here.
paxdiablo