简体   繁体   English

C 在 XUbuntu 上编程多线程

[英]C Programming multiple threads on XUbuntu

I'm trying make the program run multiple threads to it connects to different ports.我正在尝试使程序运行多个线程以连接到不同的端口。 I successfully made it work on a single thread but not multiple.我成功地让它在单个线程上工作,但不是多个。

Below I have posted the code of what I'm using on XUbuntu.下面我发布了我在 XUbuntu 上使用的代码。

server.c服务器.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 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);
 }

Problem is not clear what needs to be implemented.问题是不清楚需要实施什么。 If various ports sockets have to accept, then it has to happen in thread function as well as recv call.如果套接字必须接受各种端口,那么它必须发生在线程函数以及 recv 调用中。 In server function there are accept and recv calls which are blocking by default.在服务器功能中有默认情况下阻塞的接受和接收调用。

The main function should wait for connections.主函数应该等待连接。 Upon receiving a request from the client, you create a thread that will handle this specific connection.收到来自客户端的请求后,您将创建一个线程来处理此特定连接。 So you will create the threads in the loop, meaning, you can theoretically have an infinite number of threads.因此,您将在循环中创建线程,这意味着理论上您可以拥有无​​限数量的线程。 However, you can add a little logic to limit the number of threads that are existing at a particular time (thread pool).但是,您可以添加一些逻辑来限制特定时间(线程池)存在的线程数。

So your main loop can look like this:所以你的主循环看起来像这样:

 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);
    }

The server_thread function could look like: 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...
    // ...................
}

There may be unused variables here above... I just got this code from one of my projects, just removing parts that do not concern you :-)上面可能有未使用的变量......我刚刚从我的一个项目中获得了这段代码,只是删除了与您无关的部分:-)

Hope it helps希望能帮助到你

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM