C Программирование нескольких потоков в XUbuntu - PullRequest
0 голосов
/ 21 января 2019

Я пытаюсь заставить программу запускать несколько потоков, чтобы она подключалась к разным портам, я успешно заставил ее работать на одном потоке, но не на нескольких, и я не очень хорош в C. Я искал на stackoverflow, но я не сделалнайти что-нибудь полезное или, может быть, я не знаю, как я могу реализовать их в моей программе

Ниже я разместил код того, что я использую на XUbuntu

Спасибо в Advanced

server.c

#include <stdio.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>

// File io storing in lof file
#include "server_portLog.h"
// Thread used to create sockets
#include "sockets_pthread.h"

#define BUFFER_SIZE 1024

int main(int argc, char *argv[]) {  
// Server port number
//int portNumber = atoi(argv[1]);

// sockfd: ip-address sockit, newsockfd: socket from resiving     client , portNum: Wich port will be lisenting, num_bytes: recived data     from client
int sockfd, newsockfd, num_bytes;
// buffer: will send & recive values from the server
char buffer[BUFFER_SIZE];
struct sockaddr_in serv_addr, cli_addr;
socklen_t clilen = sizeof(cli_addr);

// Geting all ports from comand line parameters and creating a socket for each
int numPorts = argc - 1;
struct port varPorts[numPorts];
pthread_t portsSockets[numPorts];
for (int i = 0; i < numPorts; i++) {
    varPorts[i].portNumber = atoi(argv[i + 1]);
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_create(&portsSockets[i], &attr, createSocket, &varPorts[i]);
}

// Infinet loop too keep liseting even after connection to client closes
while (1) {
    // After that all the ports entered have a socket of their own the program runs them paralel together to see if any client tries to connect with one of the ports
    for (int i = 0; i <= numPorts; i++) {
        pthread_join(&portsSockets[i], NULL);
        /* Start listening for the clients (thread blocks) */
        if (listen(varPorts[i].sockfd, 5) != 0) {
            printf("Error: listen() failed for port: %d \n", varPorts[i].portNumber);
            //return 3;
        }

        // Accepting connection from client & creating socket with that client data
        newsockfd = accept(varPorts[i].sockfd, (struct sockaddr *)&cli_addr, &clilen);
        if (newsockfd < 0) {
            printf("Error: accept() failed for port: %d \n", varPorts[i].portNumber);
            //return 4;
        }

        /* To send recive data */
        // Clearing buffer
        memset(buffer, 0, BUFFER_SIZE);

        // Show data recived from client
        num_bytes = recv(newsockfd, buffer, BUFFER_SIZE-1, 0);
        if (num_bytes < 0) {
            printf("Error: recv() failed for port: %d \n", varPorts[i].portNumber);
            //return 5;
        }

        // Checking version of server if LOGFILE it creares a file to store the ports
        #if defined LOGFILE
        // Checking if user wrote a fileName for the logs or going to use the defualt log file
        if (argc == 3) {
            char *textFile = argv[argc-1];
            serverLogFile_Custom(buffer, textFile);
        }
        else {
            serverLogFile_Defualt(buffer);
        }
        #else
        // Print the port numbers that connect to server
        printf("Recieved: Client using port- %s to connect \n", buffer);
        #endif
        // Closing connection with client
        close(newsockfd);
    }
}
return 0;
 }

Sockets_pthreads.h

   #include <pthread.h>

struct port {
int portNumber;
int sockfd;
};

 void* createSocket(void* portNumber) {
// sockfd: ip-address sockit, newsockfd: socket from resiving    client , portNum: Wich port will be lisenting, num_bytes: recived data    from client
int sockfd, newsockfd, num_bytes;
// buffer: will send & recive values from the server
//char buffer[BUFFER_SIZE];
struct sockaddr_in serv_addr, cli_addr;
socklen_t clilen = sizeof(cli_addr);

struct port *portStruct = (struct port*) portNumber;
// Creating a new sockit with ip-Protocol_tcp
    // Parameters: Internet-domain, socket-stream, TCP-protocol
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd < 0) {
    printf("Error: Failed to open socket for port: %d \n", portStruct->portNumber);
    //return 1;
}

// Seting all bits in padding-field to 0 
memset(&serv_addr, 0, sizeof(serv_addr));
// Initializing socket in sockaddr_in (stucture)
serv_addr.sin_family = AF_INET; // Seting family-Internet
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portStruct->portNumber); // Setting portNum (passed in command line)

// Binding the address-structure to the socket
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
    printf("Error: bind() failed for port: %d \n", portStruct->portNumber);
    //return 2;
}
// Geting sockfd
portStruct->sockfd = sockfd;

pthread_exit(0);
 }

Ответы [ 2 ]

0 голосов
/ 21 января 2019

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

Таким образом, ваш основной цикл может выглядеть следующим образом:

 while (1) {
        // accept: wait for a connection request 
        childfd = accept(parentfd, (struct sockaddr *) &clientaddr, (socklen_t *) &clientlen);
        if (childfd < 0){
            fprintf(stderr,"ERROR on accept");
            continue;
        }

        hostaddrp = inet_ntoa(clientaddr.sin_addr);
        if (hostaddrp == NULL){
            fprintf(stderr,"ERROR on inet_ntoa\n");
            continue;
        }
        fprintf(stdout,"server established connection with client\n");

        pthread_t new_thread;
        newSock     = malloc(1);
        *newSock    = childfd;
        if( pthread_create( &new_thread , NULL ,  server_thread , (void*) newSock) < 0){
            bzero(logMsg, MAXSTRING);
            sprintf(logMsg, "Thread for connection %d could not be created",childfd);
            fprintf(stderr, "%s\n", logMsg);
            continue;
        }
        fprintf(stdout, "thread created for connection %d\n", childfd);
    }

Функция server_thread может выглядеть следующим образом:

void *server_thread(void* clientSock){
    int                 childfd = *(int*)clientSock;
    char                buf[MAXLINE];       // message buffer
    int                 n;                  // message byte size
    char                logMsg[MAXSTRING];
    size_t              siz_failresp;

    // read: read input string from the client
    bzero(buf, MAXLINE);
    n = (int) read(childfd, buf, MAXLINE);
    if (n < 0){
        sprintf(logMsg, "ERROR reading from socket");
        fprintf(stderr,"%s", logMsg);
        close(childfd);
        fprintf(stdout, "Client %d disconnected \n=================\n", childfd);
        //Free the socket pointer
        free(clientSock);
        return NULL;
    }

    // else, do processing of data received...
    // ...................
}

Здесь могут быть неиспользуемые переменные выше ... Я только что получил этот код из одного из моих проектов, просто удаляя части, которые вас не касаются :-)

Надеюсь, это поможет

0 голосов
/ 21 января 2019

Проблема не ясна, что нужно реализовать.Если необходимо принимать разные сокеты портов, то это должно происходить как в функции потока, так и в вызове recv.В функции сервера есть вызовы accept и recv, которые по умолчанию блокируются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...