XUbuntu 上的 C 多线程编程

标签 c multithreading

我正在尝试让程序运行多个线程以连接到不同的端口。我成功地让它在单个线程上工作,但不能在多个线程上工作。

下面我发布了我在 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 socket, newsockfd: socket from receiving     client, portNum: Which port will be listening, num_bytes: received data     from client
int sockfd, newsockfd, num_bytes;
// buffer: will send & receive values from the server
char buffer[BUFFER_SIZE];
struct sockaddr_in serv_addr, cli_addr;
socklen_t clilen = sizeof(cli_addr);

// Getting all ports from command 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]);
}

// Infinite loop too keep listening even after connection to client closes
while (1) {
    // After that all the ports entered have a socket of their own the program runs them parallel 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 receive data */
        // Clearing buffer
        memset(buffer, 0, BUFFER_SIZE);
    
        // Show data received 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 creates a file to store the ports
        #if defined LOGFILE
        // Checking if user wrote a fileName for the logs or going to use the default 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("Received: 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 socket, newsockfd: socket from receiving    client, portNum: Which port will be listening, num_bytes: received data    from client
int sockfd, newsockfd, num_bytes;
// buffer: will send & receive 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 socket 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;
}

// Setting 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 调用中。在服务器函数中有默认情况下阻塞的 accept 和 recv 调用。

关于XUbuntu 上的 C 多线程编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54282449/

相关文章:

c - 标签只能作为语句的一部分使用 Error

C 编程 - while 循环中的逗号运算符

r - 在 R 中以多线程方式将函数应用于 DataFrame 或矩阵中的每个单元格

c - 在 for 循环中重复使用 switch 语句

python - 以 Root 身份执行 Python 脚本(seteuid 与 c-wrapper)

在 UEFI 中创建线程

python - Django 中的线程在生产环境中不起作用

multithreading - 在Apple的Cocoa API中,为什么从主线程调用NSApplicationMain很重要?

iphone - iOS 应用未能及时启动 0x000000008badf00d - applicationDidBecomeActive 延迟

python - 什么是不是 xml 的 c 的好的配置文件库(最好有 python 绑定(bind))?