写一个TCP Echo程序?

时间:2012-07-18 20:36:15

标签: socketserver tcpsocket

我正在尝试编写一个TCP Echo程序,它应该打开一个TCP服务器套接字,接受至少一个连接,并回显所有收到的数据。至少,该程序应该在指定的端口上启动并运行(exe:端口4444“。理想情况下,它会询问端口号(来自命令行,命令行参数或配置文件),尝试在该端口上打开,并报告是否发生错误。

该程序应该使用来自Windows或Linux的telnet命令或任何操作系统中的任何终端仿真器进行测试。该用途使用Telnet或Hyperterminal连接到正在运行的程序。输入的任何内容都应立即回显。

到目前为止,我有以下内容:

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <errno.h>


#define MAXCONNECTING 1000    //Max connection requests
#define BUFFERSIZE 128       //limits data sent per loop
#define ECHOPORT 4444


//Error checking function
//Will be called multiple times to check for errors throughout the code

void ERR(char *ERROR) {
    perror(ERROR);
    exit(1);
}

/****************************************************************************
 * Handles the connection. Receive/Send data from/to client
 ****************************************************************************/
void ClientHandle(int sock) {
    char buffer[BUFFERSIZE];
    int received = -1;

    //receive the data
    if ((received = recv(sock, buffer, BUFFERSIZE, 0)) < 0) {
        ERR("Failed to receive message from client");
    }

    //send data and check for more incoming data
    while (received > 0) {
        if (send(sock, buffer, received, 0) != received) {
            ERR("Failed to send data to client");
        }
        if ((received = recv(sock, buffer, BUFFERSIZE, 0)) < 0) {
            ERR("Failed to receive additional data from client");
        }
    }
    close(sock);
}

int main(int argc, char *argv[]) {
    /****************************************************************************
     * Get port number from command line and set to default port
     ****************************************************************************/
    char *endptr;
    short int port;

    if (argc == 2) {
        port = strtol(argv[1], &endptr, 0);
        if (*endptr) {
            fprintf(stderr, "EchoServer: Invalid Port Number.\n");
            exit(EXIT_FAILURE);
        }
    } else if (argc < 2) {
        port = ECHOPORT; //port 4444
    } else {
        fprintf(stderr, "EchoServer: Invalid arguments.\n");
        exit(EXIT_FAILURE);
    }

    /****************************************************************************
     * Server Configuration. Creating the socket
     ****************************************************************************/

    int serversock, clientsock;
    struct sockaddr_in echoserver, echoclient;

    if (argc != 2) {
        fprintf(stderr, "USING: echoserver Port: 4444\n");
        exit(1);
    }
    //Creating the TCP socket
    if ((serversock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
        ERR("Failed to create socket");
    }
    //Constructing the server sockaddr_in structure
    memset(&echoserver, 0, sizeof(echoserver)); //clear struct
    echoserver.sin_family = AF_INET;             //internet ip
    echoserver.sin_addr.s_addr = htonl(INADDR_ANY); //listen to any ip address
    echoserver.sin_port = htons(atoi(argv[1])); //server port


    /*****************************************************************************
     * Bind and Listen
     *****************************************************************************/
    if (bind(serversock, (struct sockaddr *) &echoserver, sizeof (echoserver)) < 0) {
        ERR("Failed to bind the server socket");
    }
    if (listen(serversock, MAXCONNECTING) < 0) {
        ERR("Failed to listen on server socket");
    }

    /*****************************************************************************
     * Accepting the transmission
     *****************************************************************************/
    while (1) {
        unsigned int clientleng = sizeof (echoclient);

        if ((clientsock = accept(serversock, (struct sockaddr *) &echoclient, &clientleng)) < 0) {
            ERR("Failed to accept connection from client");
        }
        fprintf(stdout, "Client connected: %s\n", inet_ntoa(echoclient.sin_addr));
        ClientHandle(clientsock);
    }
    return (0);
}

/*****************************************************************************************/

谁能看到我哪里出错了?我可以使用以下命令在终端中找到该程序:g ++ EchoServer.cpp -0 EchoServer,然后是:./ EchoServer

输出只给了我: 使用:echoserver端口:4444

我试图telnet到它,但我对这个东西很新。请帮忙!!

1 个答案:

答案 0 :(得分:0)

假设您在上面的文本框中包含了当前目录中名为EchoServer.cpp的文件,您可以运行以下代码来演示它是否正常工作:

g++ EchoServer.cpp -o EchoServer

编译完成后,您将在同一目录中有一个名为EchoServer的可执行文件。

如果你只是打电话,你会收到下面的神秘信息,这意味着要使用可执行文件,你必须告诉它使用哪个端口号。

USING: echoserver Port 4444

为了证明它有效,我们将把这个过程放在后台。为此,我们使用&符号(&amp;)将其转换为作业。

EchoServer 4444 &

这应该返回一个作业编号和一个进程标识符(你的将不同),因此:

[1] 53912

您可以使用jobs命令查看它正在运行:

[1]+  Running                 ./EchoServer 4444 &

您现在可以telnet到此以查看它是否正常工作:

telnet localhost 4444

您应该看到:

Trying 127.0.0.1...
Client connected: 127.0.0.1
Connected to localhost.
Escape character is '^]'.

当您按Enter键或返回时,您输入的任何内容都将被发回给您。尝试输入Hello并按回车。

完成后,您可以按住控制键,然后按住方括号键(之后可能需要按返回键)。这将带您进入telnet提示符,您应键入quit以离开。

要关闭EchoServer可执行文件,您可以将作业恢复到前台并使用Control-C按键将其停止。假设您的作业为1(您可以再次运行jobs来检查数字),您可以运行以下命令将其恢复到前台:

fg 1

您现在已经在EchoServer进程中有效了,按Control-C将结束它。

那就是它!你完成了。您已成功证明该程序正常运行。