【问题标题】:How to check existing connections to socket server in Linux?如何在 Linux 中检查与套接字服务器的现有连接?
【发布时间】:2021-03-17 10:35:27
【问题描述】:

我有一个项目,我需要通过套接字发送文件进行简单的聊天。我想知道 C 中的套接字编程中是否有任何函数可以让我检查现有连接(我需要向每个连接的客户端发送消息)。我试图通过创建一个数组并将我的套接字保存到它来做到这一点,但是由于fork() 它不起作用,每个客户端都有自己的数组并且它们不匹配。我的服务器是用 C 编写的,我的客户端是用 Python 编写的。以下是我的代码:

服务器:

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

#define PORT 9992

int main(){
    char separator[4];
    int iterator = 0;
    int clients[32];
    separator[0] = '|';
    int sockfd, ret;
    char name[32];
     struct sockaddr_in serverAddr;

    int newSocket;
    struct sockaddr_in newAddr;

    socklen_t addr_size;

    char buffer[1024];
    pid_t childpid;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd < 0){
        printf("[-]Error in connection.\n");
        exit(1);
    }
    printf("[+]Server Socket is created.\n");

    memset(&serverAddr, '\0', sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(PORT);
    serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    ret = bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
    if(ret < 0){
        perror("");
        printf("[-]Error in binding.\n");
        exit(1);
    }
    printf("[+]Bind to port %d\n", PORT);

    if(listen(sockfd, 10) == 0){
        printf("[+]Listening....\n");
    }else{
        perror("");
        printf("[-]Error in binding.------\n");
    }


    while(1){
        newSocket = accept(sockfd, (struct sockaddr*)&newAddr, &addr_size);
        printf("%i", newSocket);

        for (size_t i = 0; i <= iterator; i++) {
            // printf("%i\n", iterator);
            if(clients[i] == 0){
                clients[i] = newSocket;
            }
            else if(i == iterator){
                clients[iterator] = newSocket;
                iterator ++;
                break;
            }
        }

        if(newSocket < 0){
            perror("");
            printf("new socket < 0");
            exit(1);
        }
        printf("Connection accepted from %s:%d ", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
        recv(newSocket, name, 32, 0 );
        printf("%s \n", name);
        if((childpid = fork()) == 0){
            // perror("");
            // close(sockfd);

            while(1){
                for (size_t i = 0; i < iterator; i++) {
                    printf("%i\n", clients[i]);
                }
                recv(newSocket, buffer, 1024, 0);
                if(strcmp(buffer, "/exit") == 0){
                    printf("Disconnected from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
                    perror("");
                    // deleting disconnecting client from array of clients
                    for (int i = 0; i < iterator; i++) {
                        // printf(clients[i]);
                        if(clients[i] == newSocket){
                            clients[i] = 0;
                            printf("Element deleted \n");
                        }
                        break;
                    }
                    break;
                }else{

                    if(strcmp(buffer, "/who") == 0){
                        perror("");
                        for (size_t i = 0; i < iterator; i++) {
                            printf("%i\n", clients[i]);
                            bzero(buffer, sizeof(buffer));
                        }
                    }
                    perror("");
                    printf("%s: %s\n",name, buffer);
                    for (size_t i = 0; i < iterator; i++) //sending message to every client {
                        send(clients[i], name, strlen(name), 0);
                        send(clients[i], separator, strlen(separator), 0);
                        send(clients[i], buffer, strlen(buffer), 0);

                    }
                    bzero(buffer, sizeof(buffer));
                    // bzero(name, sizeof(name));

                }
            }
        }

    }

    close(newSocket);
    // perror("");

    return 0;
}

我的客户端.py:

import socket
import sys
import time

host = '127.0.0.1'
port = 9992
buffer = ''
# create socket
print('# Creating socket')
try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
    print('Failed to create socket')
    sys.exit()

print('# Getting remote IP address')
try:
    remote_ip = socket.gethostbyname( host )
except socket.gaierror:
    print('Hostname could not be resolved. Exiting')
    sys.exit()

# Connect to remote server
print('# Connecting to server, ' + host + ' (' + remote_ip + ')')
name = input("What will be your name?: ")
namePY = name
name += "\0"
s.connect((remote_ip , port))
s.send(name.encode())



# Send data to remote server
print('Connection established with server, your name is: {}'.format(name))
while True:
    buffer = input("{}: ".format(namePY))
    buffer += '\0'
    s.send(buffer.encode())
    if(buffer == "/exit\0"):
        s.close()
        break
    # print('# Receive data from server')
    time.sleep(0.1)
    reply = s.recv(1024).decode()
    replyArray = reply.split('|')
    if replyArray[0] == namePY:
        pass
    else:
        print('{}: {}'.format(replyArray[0], replyArray[1]))

【问题讨论】:

  • “检查现有连接”是什么意思?就套接字而言,唯一涉及套接字的系统调用是socket()bind()listen()connect()accept()
  • 是啊....你已经有很多失败了,例如'recv(newSocket, buffer, 1024, 0);' - 您必须正确且完整地处理从 send()、recv() 等系统调用返回的结果。如果 C 库函数需要 NUL 终止的 char 数组,则必须确保此类参数保证为 NUL 终止。
  • 您应该首先阅读有关 TCP/IP 的更多信息。您应该为传入的客户使用多线程 - 查看接受并为每个 Client-Com 提供一个线程。来自接受存储的套接字以列表或类似形式存储。现在您可以遍历列表中的所有套接字并发送/接收消息。您还需要对服务器和客户端进行更多的异常处理:客户端断开连接、服务器关闭套接字等等。
  • 即使服务器实现在 PYTHON 中:您也可以将其适配为 C:stackoverflow.com/questions/10810249/… 完成此操作后,我们可以讨论您要发送/接收的数据

标签: c++ c linux sockets


【解决方案1】:

对于其中不同客户端相互交互的多客户端网络服务器,使用多线程设计比使用多进程设计更容易。通过在同一进程中为每个客户端生成一个新线程,您将能够在所有线程上共享内存结构。对于多个进程,您必须使用管道或共享内存段之类的东西,这更加困难(即使考虑到在多线程情况下需要像互斥锁这样的同步原语)。此外,一个进程无法直接写入另一个进程的套接字。它可以做的最好的事情就是让其他进程来写。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-04
    • 2019-12-10
    • 1970-01-01
    • 2011-07-23
    • 2021-02-18
    • 2015-09-29
    相关资源
    最近更新 更多