我有一台服务器,它应该一次允许一个客户端连接,执行命令,然后关闭。服务器保存“当前连接”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/