C ++奇怪的套接字数据

时间:2010-08-11 04:45:07

标签: c++ sockets

嘿伙计们,这是我的代码。

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; 
} 

现在,我对套接字很新,我只想尝试一下,但我确实对PHP中的套接字有一些经验。我在我的linux机器上通过putty使用telnet来测试这个,我不知道是否会导致任何问题,但服务器输出一些奇怪的字符,我不知道为什么。我认为它与缓冲区有关,但我不太确定。我可以通过telnet将“hi”之类的东西发送到服务器并输出它们就好并将它们发回给我但是当我发送像“hoobla”这样的东西时它会启动时髦的角色。任何的意见都将会有帮助!

提前致谢!

2 个答案:

答案 0 :(得分:15)

由于recv没有空终止您的缓冲区,因此打印出垃圾。

以下代码中的重要部分是:

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;

它将在尝试打印之前正确终止缓冲区,并删除尾随换行符(如果存在)(并允许客户端区分输入和回显行)。

这个(一个完整的程序)效果更好:

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;
}

在客户端:

$ 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.

,在服务器端:

$ ./testprog
Waiting for connections....
Recived new connection from 127.0.0.1
hello
my name is pax
and you?
Waiting for connections....

答案 1 :(得分:1)

问题是buffer不能保证包含字符串终止的空字符。在buffer[BUFSIZE-1] = '\0'之前添加行cout << buffer

更好的是,实际记录收到的字节数,并使用该信息确定是否超出了缓冲区。