如何在 Linux 中检查与套接字服务器的现有连接?

kap*_*lec 0 c c++ sockets linux

我有一个项目,我需要通过套接字发送文件进行简单的聊天。我想知道 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;
}

Run Code Online (Sandbox Code Playgroud)

我的客户.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]))

Run Code Online (Sandbox Code Playgroud)

Sne*_*tel 5

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

\n