簡體   English   中英

C 在 XUbuntu 上編程多線程

[英]C Programming multiple threads on XUbuntu

我正在嘗試使程序運行多個線程以連接到不同的端口。 我成功地讓它在單個線程上工作,但不是多個。

下面我發布了我在 XUbuntu 上使用的代碼。

服務器.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);
 }

問題是不清楚需要實施什么。 如果套接字必須接受各種端口,那么它必須發生在線程函數以及 recv 調用中。 在服務器功能中有默認情況下阻塞的接受和接收調用。

主函數應該等待連接。 收到來自客戶端的請求后,您將創建一個線程來處理此特定連接。 因此,您將在循環中創建線程,這意味着理論上您可以擁有無​​限數量的線程。 但是,您可以添加一些邏輯來限制特定時間(線程池)存在的線程數。

所以你的主循環看起來像這樣:

 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...
    // ...................
}

上面可能有未使用的變量......我剛剛從我的一個項目中獲得了這段代碼,只是刪除了與您無關的部分:-)

希望能幫助到你

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM