c - 服务器认为2个不同IP的客户端是同一个客户端(C Socket编程)

标签 c sockets server

我有一台服务器,它应该一次允许一个客户端连接,执行命令,然后关闭。服务器保存“当前连接”IP 地址的数组列表,以便它知道接受来自谁的命令。 问题是我有两个在相似 IP 地址上运行的客户端,被视为同一客户端。

示例: 客户端 A 的 IP 地址为 255.255.255.153。我告诉它连接,一切正常。 客户端 B 的 IP 地址为 255.255.255.156。我告诉它连接,服务器说它已经连接了。

我的strcmp不正确吗?难道是别的什么?请帮忙。

// Variable Declarations

int SIZE = 10; // Max number of agents
char *agents[SIZE], // List of current connections
     *times[SIZE]; // List of connection times
char buffer[MAXBUF];
int bytes_read = 0;
int total_bytes_read = 0;
int found = 0, // Bool flag
    i;
struct tm  ts;
struct timeval connected[SIZE],
               current,
               difference;
       time_t TIME;

// Initialize array to NULL
for(i = 0; i < SIZE; i++) {
    agents[i] =  NULL;
}

// Infinite Loop
while (true) {
    struct sockaddr_in client;
    int clientSocket;
    socklen_t clientLength = sizeof(client);
    memset(&client, 0, clientLength);
    clientSocket = accept(sd, (struct sockaddr *)&client, &clientLength);

    memset(buffer,0,MAXBUF);
    bytes_read = read(clientSocket, buffer, MAXBUF);
    if (bytes_read < 0)
        break;
    fprintf(stdout,"\nRead %d bytes: [%s]\r\n", bytes_read,buffer);

    char *connectedIP = inet_ntoa(client.sin_addr);

    // Option 1:
    if ((strcmp(buffer, "#JOIN")) == 0) { // Join list of connected agents
        found = 0;

        // Get current time for log
        TIME = time(NULL);
        ts = *localtime(&TIME);

        // Print message to log
        char buf[80];
        strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", &ts);
        fprintf(log, "%s: Received a \"#JOIN\" action from agent \"%s\"", buf, connectedIP);
        fprintf(log, "\n\n");
        fflush(log);

        printf("\n%s Joining", connectedIP);
        fflush(stdout);
        // Handle #JOIN request appropriately
        for (i = 0; i < SIZE; i++) {
            printf("\nAgent[%d] == %s", i, agents[i]);

            if (agents[i] == NULL) {

            }
            else if (strcmp(agents[i], connectedIP) == 0){ // Agent found in list
                found = 1;

                printf("\n%s is equal to %s", agents[i], connectedIP);
                fflush(stdout);

                // Write to agent
                char response[] = "#ALREADY MEMBER";
                write (clientSocket, response, strlen(response));

                // Get time for log
                TIME = time(NULL);
                ts = *localtime(&TIME);

                // Write to log
                char buf[80];
                strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", &ts);
                fprintf(log, "%s: Responded to agent \"%s\" with \"#ALREADY MEMBER\"", buf, connectedIP);
                fprintf(log, "\n\n");
                fflush(log);
                i = SIZE;
            }
        }
        if (found == 0) { // Save IP to list/queue
            for(i = 0; i < SIZE; i++) {
                if (agents[i] == NULL) {

                    // Save IP to array
                    agents[i] = connectedIP;

                    printf("\nagents[%d] = %s\n", i, connectedIP);
                    fflush(stdout);

                    // Save time to arrays
                    gettimeofday(&connected[i], NULL);
                    TIME = time(NULL);
                    times[i] = TIME;
                    ts = *localtime(&TIME);

                    // Write to log
                    char buf[80];
                    strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", &ts);
                    fprintf(log, "%s: Responded to agent \"%s\" with \"#OK\"", buf, connectedIP);
                    fprintf(log, "\n\n");
                    fflush(log);

                    // Write to agent
                    char response[] = "#OK";
                    write (clientSocket, response, strlen(response));
                    i = SIZE;
                }
            }
        }
        memset(&client, 0, clientLength);
    }

最佳答案

inet_ntoa() 的 POSIX 规范包括信息:

The inet_ntoa() function shall convert the Internet host address specified by in to a string in the Internet standard dot notation.

The inet_ntoa() function need not be thread-safe.

inet_ntoa() 的 Linux 手册页更明确地说明其行为方式以及 POSIX 警告在该平台上的含义:

The inet_ntoa() function converts the Internet host address in, given in network byte order, to a string in IPv4 dotted-decimal notation. The string is returned in a statically allocated buffer, which subsequent calls will overwrite.

正如我在 comment 中指出的那样(是的,该评论的第一部分不准确 - iPhone 应用程序上的代码很难阅读):

…but the chances are that you are using the same space for all the agents, so if you iterated over the connected agents, printing the names, you'd find they're all the same. I'd expect something like a strdup(connectedIP) there.

这意味着,由于您的代码只是将 inet_ntoa() 返回的指针保存在 agents 数组中,因此该数组始终包含最后查找的主机。您必须从 inet_ntoa() 获取结果的副本并保存,并管理存储。最简单的方法是使用 strdup() 获取副本,但您必须记住在连接关闭时释放它。

使用 strdup() 或等效机制应该可以解决您眼前的问题。当心内存泄漏。

关于c - 服务器认为2个不同IP的客户端是同一个客户端(C Socket编程),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47620679/

相关文章:

c - Windows 和 Linux 之间通过套接字进行通信的问题

javascript - Node.js模块之间的通信

java - Android 客户端/服务器通信的最佳实践

linux - 如何sudo通过ssh运行本地脚本

node.js - Azure 上的 Strapi 无法运行

hibernate - 如何自动 hibernate 并重新唤醒我的 Ubuntu 服务器?

c - glCallLists 是否比一次调用一个显示列表更有效?

c++ - 为什么我们需要一个单位 vector (换句话说,为什么我们需要对 vector 进行归一化)?

c - Realloc() 不更改已分配内存的内存地址?

c# - 重叠 Socket.BeginSend/EndSend 调用的可预测行为