C 客户机/服务器程序中的线程

C 客户机/服务器程序中的线程,c,multithreading,client-server,C,Multithreading,Client Server,对于大学,我正在开发一个本地中继聊天。我必须编程一个聊天服务器和客户端,它只能在同一台计算机上的不同终端窗口上使用线程和FIFO发送消息 FIFOs部分我没有问题,线程部分让我有些头疼 服务器有一个线程用于接收来自FIFO(由所有客户端使用)的命令,另一个线程用于连接的每个客户端 对于每个连接的客户端,我需要知道特定的信息。首先,我使用了全局变量,它的工作时间很长,因为只有一个客户端连接,这是一个聊天,单独聊天 因此,理想情况下,我会有一些数据,如: -昵称 -名称 -电子邮件 -等等 每个已连

对于大学,我正在开发一个本地中继聊天。我必须编程一个聊天服务器和客户端,它只能在同一台计算机上的不同终端窗口上使用线程和FIFO发送消息

FIFOs部分我没有问题,线程部分让我有些头疼

服务器有一个线程用于接收来自FIFO(由所有客户端使用)的命令,另一个线程用于连接的每个客户端

对于每个连接的客户端,我需要知道特定的信息。首先,我使用了全局变量,它的工作时间很长,因为只有一个客户端连接,这是一个聊天,单独聊天

因此,理想情况下,我会有一些数据,如:

-昵称
-名称
-电子邮件
-等等

每个已连接的客户端。然而,我不知道怎么做

我可以创建一个client_data[MAX_NUMBER_OF_THREADS],其中client_data是一个结构,包含我需要访问的所有内容,但这需要在服务器和客户端之间的每次通信中请求阵列client_data中的客户端id,这似乎不太实际

我也可以在创建线程后立即实例化客户机_数据,但它只在该块中可用,这也不是很实用


正如你所看到的,我在这里需要一些指导。非常感谢您对任何相关信息的任何评论、代码或链接。

我不知道您使用的是什么语言,但这里有一些基本想法:

  • 在线程(可能是主线程)中启动服务器
  • 服务器的while循环将在接受套接字连接时阻塞
  • 当接受套接字连接时,它应该生成一个新线程来处理连接
  • 在新线程中开始与客户端通信
简单的套接字服务器循环如下所示(在Java中):

如果您想知道它是做什么的,
ClientWorker
是可用的。在C#中,如果你正在创建一个
新线程
,不要忘记将其
IsBackground
属性设置为
true
,这样当你的应用程序关闭时,线程就会关闭,即没有挂起的线程

请记住:接受套接字连接或从套接字接收数据通常是阻塞调用,这意味着您的线程将阻塞,直到有人连接到套接字或数据通过套接字到达

在C#中:

  • 聊天客户端:
  • 聊天服务器:
  • 基本客户端/服务器:
  • 在Java中:

  • 聊天客户端/服务器:
  • Nakov聊天客户端/服务器:
  • 在C中++

  • 关于代码项目:
  • 另一个代码项目TCP/IP聊天客户端/服务器:
  • 更新 不做全局变量,只需为客户端帐户定义一个
    struct
    ,并为每个用户声明一个帐户变量。。。以下是如何定义帐户信息:

    struct account {
       char nickname[32];
       char first_name[32];
       char last_name[32];
       char e_mail[32];
       char password[32];
    };
    
    当客户端发送消息时,它应该具有标准格式:
    FROM | TO | CONTENT

    struct message{
       char nickname_from[32];
       char nickname_to[32]; // optional
       char msg_content[256];
    };
    

    将每条
    消息
    放在fifo[队列]上,您将获得识别发送消息的人所需的所有信息。

    以下是一些可能几乎要运行的psuedo代码。注意,我并没有释放我分配的内容,我并没有检查错误,我只是试图演示如何将结构传递给线程并使用简单的互斥

    有一件事需要注意,线程的函数指针指定了一个
    void*
    参数,它可以是任何类型。在线程中,我们假设将线程参数强制转换为我们定义的要使用的类型是安全的。如果要传递多个可能的类型,则必须小心:)

    我不太清楚您的程序的结构,或者您是如何处理线程的,但这里有一个关于如何向线程传递数据的不可知方法的简短示例:

    typedef struct client {
        char *firstname;
        char *lastname;
        char *email;
        char *nickname
    } client_t;
    
    
    pthread_mutex_t client_lock = PTHREAD_MUTEX_INITIALIZER;
    
    void *client_thread(void *threadarg)
    {
        client_t *client = (client_t *) threadarg;
    
        pthread_mutex_lock(&client_lock);
        /* read and write to client structure */
        pthread_mutex_unlock(&client_lock);
    
        /* do some other stuff */
        pthread_exit(NULL);
    }
    
    int main(void)
    {
        client_t *client;
        pthread_t cthread;
    
        client = (client_t *)malloc(sizeof(struct client));
        if (client == NULL)
          return 1;
    
        client->firstname = strdup("Joe Public");
        /* set the rest of the data */
    
        pthread_create(&cthread, NULL, (void *)client_thread, (void *)client);
        /* join / detach / etc */
    
        /* Free all the structure members and the structure itself */
    
       return 0;
    }
    

    我很确定这就是你要问的问题?

    我感谢你的回答,但我必须在没有套接字的情况下实现这一点。只有FIFO和线程。这是一个本地中继聊天。@nunos,这与阻塞i/o的概念相同:您将阻塞从任何地方读取的数据,而不是阻塞套接字。您仍然需要为每个“已连接”的客户端创建一个新线程,并建立一个与客户端通信的专用i/o通道。每个客户端的线程显然不能扩展,因此如果您想要一个非常健壮的服务器,您可以使用非阻塞IO和类似select()的东西从单个线程监视多个套接字。但对于一些简单的事情,那么每个客户端的线程就可以了。您和Lirik的回复让我对如何处理这个问题有了一些见解。我现在有了一个开始实现线程的想法。谢谢
    typedef struct client {
        char *firstname;
        char *lastname;
        char *email;
        char *nickname
    } client_t;
    
    
    pthread_mutex_t client_lock = PTHREAD_MUTEX_INITIALIZER;
    
    void *client_thread(void *threadarg)
    {
        client_t *client = (client_t *) threadarg;
    
        pthread_mutex_lock(&client_lock);
        /* read and write to client structure */
        pthread_mutex_unlock(&client_lock);
    
        /* do some other stuff */
        pthread_exit(NULL);
    }
    
    int main(void)
    {
        client_t *client;
        pthread_t cthread;
    
        client = (client_t *)malloc(sizeof(struct client));
        if (client == NULL)
          return 1;
    
        client->firstname = strdup("Joe Public");
        /* set the rest of the data */
    
        pthread_create(&cthread, NULL, (void *)client_thread, (void *)client);
        /* join / detach / etc */
    
        /* Free all the structure members and the structure itself */
    
       return 0;
    }