Squeak.ru - шаблоны программирования

Как проверить существующие подключения к серверу сокетов в 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;
}

Мой клиент.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]))

05.12.2020

  • Что означает проверка существующих соединений? Что касается сокетов, единственными системными вызовами, использующими сокеты, являются socket(), bind(), listen(), connect() и accept(). 05.12.2020
  • Ага... у вас уже много сбоев, например 'recv(newSocket, buffer, 1024, 0);' - вы ДОЛЖНЫ правильно и полностью обрабатывать результат, возвращаемый системными вызовами, такими как send(), recv(). Если для библиотечной функции C требуется массив символов с нулевым завершением, вы ДОЛЖНЫ убедиться, что такие аргументы гарантированно заканчиваются нулевым символом. 05.12.2020
  • Сначала вы должны больше узнать о TCP/IP. И вы должны использовать многопоточность для входящих клиентов - посмотрите на принятие и предоставьте поток для каждого Client-Com. Сокет из принятого хранилища в виде списка или аналогичного. Теперь вы можете перебирать все сокеты в списке и отправлять/получать сообщения. Вам также нужно больше обработки исключений для сервера и клиента: отключение клиента, отключение сокета и т. д. 05.12.2020
  • Даже если реализация сервера находится здесь, в PYTHON: вы также можете адаптировать ее к C: "> stackoverflow.com/questions/10810249/ Как только вы это сделаете, мы можем поговорить о данных, которые вы хотите отправить/получить 05.12.2020

Ответы:


1

Для многоклиентского сетевого сервера, в котором разные клиенты взаимодействуют друг с другом, использовать многопоточный дизайн будет проще, чем многопроцессный, как у вас. Создавая новый поток для каждого клиента в одном и том же процессе, вы сможете совместно использовать структуры памяти для всех потоков. Для нескольких процессов вам придется использовать такие вещи, как конвейеры или сегменты разделяемой памяти, что сложнее (даже с учетом необходимости примитивов синхронизации, таких как мьютексы, в случае многопоточности). Кроме того, один процесс не может напрямую писать в сокеты другого процесса. Лучшее, что он может сделать, это попросить другие процессы сделать запись.

05.12.2020
Новые материалы

Угловая структура архитектуры
Обратите внимание, что эта статья устарела, я решил создать новую с лучшей структурой и с учетом автономных компонентов: https://medium.com/@marekpanti/angular-standalone-architecture-b645edd0d54a..

«Данные, которые большинство людей используют для обучения своих моделей искусственного интеллекта, поставляются со встроенным…
Первоначально опубликовано HalkTalks: https://hacktown.com.br/blog/blog/os-dados-que-a-maioria-das-pessoas-usa-para-treinar-seus-modelos-de-inteligencia-artificial- ja-vem-com-um-vies-embutido/..

Сильный ИИ против слабого ИИ: различия парадигм искусственного интеллекта
В последние годы изучению и развитию искусственного интеллекта (ИИ) уделяется большое внимание и прогресс. Сильный ИИ и Слабый ИИ — две основные парадигмы в области искусственного интеллекта...

Правильный способ добавить Firebase в ваш проект React с помощью React Hooks
React + Firebase - это мощная комбинация для быстрого и безопасного создания приложений, от проверки концепции до массового производства. Раньше (знаете, несколько месяцев назад) добавление..

Создайте API с помощью Python FastAPI
Создание API с помощью Python становится очень простым при использовании пакета FastAPI. После установки и импорта вы можете создать приложение FastAPI и указать несколько конечных точек. Каждой..

Веселье с прокси-сервером JavaScript
Прокси-серверы JavaScript — это чистый сахар, если вы хотите создать некоторую общую логику в своих приложениях, чтобы облегчить себе жизнь. Вот один пример: Связь клиент-сервер Мы..

Получить бесплатный хостинг для разработчиков | Разместите свой сайт за несколько шагов 🔥
Статические веб-сайты — это веб-страницы с фиксированным содержанием и его постоянным содержанием. Но теперь статические сайты также обрабатывают динамические данные с помощью API и запросов...