C 服务器程序停留在read()函数上,但write()函数在客户端程序中运行良好

C 服务器程序停留在read()函数上,但write()函数在客户端程序中运行良好,c,linux,sockets,network-programming,C,Linux,Sockets,Network Programming,我正在使用C语言中的套接字编程方法编写一个简单聊天室程序。我实现了客户端可以连接到服务器并向服务器发送消息,服务器应该向其他服务器分发消息 但是,当我尝试测试我的程序并尝试让两个客户端进行通信时,一些奇怪的事情发生了。如果我遵循以下步骤,就会发生奇怪的事情 运行服务器程序并等待连接 打开一个客户端程序并连接到服务器,然后发送两条消息,两条消息均成功 打开另一个客户端并执行相同操作,第一个客户端可以接收第二个客户端完美发送的消息。 但是,当我切换到第一台服务器时,尝试写入新消息并发送到要分发的服务

我正在使用C语言中的套接字编程方法编写一个简单聊天室程序。我实现了客户端可以连接到服务器并向服务器发送消息,服务器应该向其他服务器分发消息

但是,当我尝试测试我的程序并尝试让两个客户端进行通信时,一些奇怪的事情发生了。如果我遵循以下步骤,就会发生奇怪的事情

  • 运行服务器程序并等待连接
  • 打开一个客户端程序并连接到服务器,然后发送两条消息,两条消息均成功
  • 打开另一个客户端并执行相同操作,第一个客户端可以接收第二个客户端完美发送的消息。
  • 但是,当我切换到第一台服务器时,尝试写入新消息并发送到要分发的服务器时,它失败了。第二个客户端和服务器都无法接收此消息
  • 经过一些调试后,服务器程序似乎卡住了read()函数。 顺便说一句,我在我的Uubuntu18.04虚拟机的不同终端上完成了这些操作
  • 更多要点:

  • 我已经试着调试和打印我能得到的所有值,客户端程序的write()函数似乎工作正常,但服务器程序在接收线程内的第二个函数read()处停止。
  • 我认为这可能是一个关于read()函数的阻塞状态的问题,但我对网络编程是新手,不太了解 这是我问题的屏幕截图(聊天室:左边是服务器,右边是两个客户端):

    这是我的client.c和server.c代码,我已经指出了问题发生的位置

    客户C

    /*tcp client.c*/
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    //在终端获得输入时随时向服务器发送消息
    作废*发送(作废*插入)
    {
    字符发送器[80];
    //将套接字保存到int指针中
    int*SockedCopy=Socked;
    while(fgets(发送方,sizeof(发送方),stdin)){
    //只要输入字符串,就发送它
    int messageSize=strlen(发送方)+1;
    写入(*SockedCopy,&messageSize,sizeof(int));
    int i=write(*SockedCopy,sender,messageSize);//在发送消息时两者都起作用
    printf(“write over!write()返回%d\n”,i);
    //检查这是否是退出消息
    if(strcmp(发送方,“q!”)==0)
    出口(1);
    }
    }
    //从服务器接收消息
    无效*接收(无效*插入)
    {
    int*SockedCopy=Socked;
    字符接收器[80];
    而(1){
    //持续阅读信息
    int reveiverEnd=0;
    reveiverEnd=读取(*SockedCopy,接收器,1000);
    接收器[reveiverEnd]='\0';
    FPUT(接收器、标准输出);
    接收器[0]='\0';
    }
    }
    int main()
    {
    int-sockfd,n;
    pthread\u t threadSend;
    pthread_t threadReceive;
    serv、cli中的结构sockaddr_;
    char rec[1000];
    char-send[80];
    //输入用户名
    printf(“输入用户名:”);
    fgets(发送、sizeof(发送)、标准输入);
    send[strlen(send)-1]='\0';
    int MessageSize=strlen(发送);
    //创建袜子
    sockfd=套接字(PF_INET,SOCK_STREAM,0);
    //创建服务器信息
    bzero(&serv,sizeof(serv));
    serv.sin_family=PF_INET;
    serv.sin_port=htons(8888);
    serv.sin_addr.s_addr=inet_addr(“127.0.0.1”/*本地机器*/);
    //连接到服务器
    连接(sockfd,(struct sockaddr*)&serv,sizeof(struct sockaddr));
    //将用户名发送到服务器
    写入(sockfd,&MessageSize,sizeof(int));
    写入(sockfd、send、sizeof(send));
    //获取成功的连接消息
    n=读取(sockfd,rec,1000);//n标记实际长度
    rec[n]='\0';
    FPUT(记录、标准输出);
    发送[0]='\0';
    //打开发送线程
    pthread_创建(&threadSend、0、Send和&sockfd);
    //打开接收消息线程
    pthread_创建(&threadReceive、0、Receive和&sockfd);
    //合上袜子并合上两条线
    对于(int i=0;i<100;++i)
    睡眠(10万);
    pthread_退出(&threadSend);
    pthread_退出(&threadReceive);
    关闭(sockfd);
    返回0;
    }
    
    服务器.C

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <pthread.h>
    #include <sys/socket.h>
    #include <linux/in.h>
    #include <unistd.h>
    #include <unistd.h>
    
    pthread_t thread;
    pthread_t threadClient[100];
    int ServerSock;
    
    //Every client's information
    typedef struct
    {
        int sock;
        char UserName[16]; 
        struct sockaddr address;
        int addr_len;
    } connection_t;
    static connection_t conn[100];
    
    //this function distributes the messsage/status of single client to the other
    //Info is the message needed to be distributed
    int SendInfo(void* Info)
    {
        char *info = Info;
        for(int i = 0; i < 100; ++i)
            //send to the client that exists and doesn't quit room
            if(conn[i].addr_len != -1 && conn[i].addr_len != 0){
                if(send (conn[i].sock, info , strlen(info) + 1, 0) == -1)
                    printf("error occured, send to %s fail", conn[i].UserName);
                printf("send %s to %s successfully!\n", info, conn[i].UserName);
            }   
        return 0;   
    }
    
    
    //This function deals with single client, aim to receive message from this client
    //and then send them to another using SendIinfo
    void* Receive(void* clientnumber)
    {
        int* Clientnumber = clientnumber;
        while(1)
        {
            //read the message from the client
            char *Buffer;
            int messageLen = 0;
            read(conn[*Clientnumber].sock, &messageLen, sizeof(int));
            printf("receive from %d\n", messageLen);
            if(messageLen > 0)
            {
                Buffer = (char *)malloc((messageLen+1)*sizeof(char));
                read(conn[*Clientnumber].sock, Buffer, messageLen);   // the program stucks here and don't know why
    
                if(Buffer[0] != ':') continue;
                Buffer[messageLen] = '\0';
                //whether the client want to quit
                if( Buffer[1] == 'q' && Buffer[2] == '!' )
                {
                    //constitute quit message and delete this client
                    char quit[] = " quit the chat room";
                    char quitMessage[20];       
                    quitMessage[0] = '\0';
                    strcat(conn[*Clientnumber].UserName, quit); 
                    SendInfo(quitMessage);
                    conn[*Clientnumber].addr_len = -1;
                    pthread_exit(&threadClient[*Clientnumber]);
                }
                else{
                    //constitute the message
                    char begin[] = " says";
                    char messageDistribute[200];
                    messageDistribute[0] = '\0';
                    strcat(messageDistribute, conn[*Clientnumber].UserName);
                    strcat(messageDistribute, begin);
                    strcat(messageDistribute, Buffer);
                    SendInfo(messageDistribute);
                }
                free(Buffer);
            }
            else
                continue;
        }
    }
    
    
    
    //aim to accept whenever there is a client trying to connect
    void * process(void * ptr)
    {
        pthread_t clientThread[100];
        char * buffer;
        int len;
        //the number of the client connecting now
        int clientNumber = 0;      
        long addr = 0;
        while(1){
            //waiting to be connected
            if(clientNumber < 100)
            {
                conn[clientNumber].sock = accept(ServerSock, &conn[clientNumber].address, &conn[clientNumber].addr_len);
            }
            else
                break;
    
    
            //the length of the message
            read(conn[clientNumber].sock, &len, sizeof(int));
            if (len > 0)
            {
    
                //multiple information of a client
                addr = (long)((struct sockaddr_in *)&conn[clientNumber].address)->sin_addr.s_addr;
                buffer = (char *)malloc((len+1)*sizeof(char));
                buffer[len] = 0;
                read(conn[clientNumber].sock, buffer, len);
    
    
                //send success message to the client
                send (conn[clientNumber].sock, "You have entered the chatroom, Start CHATTING Now!\n", 51, 0);
    
    
                //save client's nick name
                strcpy(conn[clientNumber].UserName, buffer);
    
    
                printf("User <%s> has entered the Chatroom!\n", conn[clientNumber].UserName);
                printf("There are %d people in Chatroom now!\n",clientNumber+1);
                free(buffer);
    
                //create a thread dealing the messages from a single client
                int number = clientNumber;
                pthread_create(&threadClient[clientNumber], 0, Receive, &number);
            }
            clientNumber += 1;
    
        }
        pthread_exit(0);
    }
    
    int main(int argc, char ** argv){
        struct sockaddr_in address;
        int port = 8888;
        connection_t * connection;
    
        //create socked
        ServerSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
        //bind the socked to a port
        address.sin_family = AF_INET;
        address.sin_addr.s_addr = INADDR_ANY;
        address.sin_port = htons(port);
        if (bind(ServerSock, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) < 0)
        {
            fprintf(stderr, "error: cannot bind socket to port %d\n", port);
            return -4;
        }
    
    
        //listen for connections
        listen(ServerSock, 100);
        printf("the server is ready and listening\n");
    
    
        //creating a thread dealing with connections
        pthread_create(&thread, 0, process, (void *)connection);
    
    
        //keep this program working
        for(int i = 0; i < 100; ++i)
            sleep(10000);
    
    
        //close socked and thread
        pthread_detach(thread);
        close(ServerSock);
        return 0;
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    pthread\u t线程;
    pthread_t threadClient[100];
    int-ServerSock;
    //每个客户的信息
    类型定义结构
    {
    int袜子;
    字符用户名[16];
    结构sockaddr地址;
    国际地址;
    }连接;
    静态连接接头[100];
    //此功能将单个客户端的消息/状态分发给其他客户端
    //信息是需要分发的消息
    int SendInfo(无效*信息)
    {
    char*info=info;
    对于(int i=0;i<100;++i)
    //发送到已存在且未退出房间的客户端
    if(conn[i].addr\u len!=-1&&conn[i].addr\u len!=0){
    如果(发送(连接[i].sock,info,strlen(info)+1,0)=-1)
    printf(“发生错误,发送到%s失败”,连接[i]。用户名);
    printf(“将%s成功发送到%s!\n”,信息,连接[i]。用户名);
    }   
    返回0;
    }
    //此函数用于处理单个客户端,目的是从该客户端接收消息
    //然后使用SendIinfo将它们发送给另一个
    作废*接收(作废*客户号)
    {
    int*Clientnumber=Clientnumber;
    而(1)
    {
    //从客户端读取消息
    字符*缓冲区;
    int messageLen=0;
    读取(conn[*Clientnumber].sock,&messageLen,sizeof(int));
    printf(“从%d接收”,messageLen);
    如果(messageLen>0)
    {
    Buffer=(char*)malloc((messageLen+1)*sizeof(char));
    read(conn[*Clientnumber].sock、Buffer、messageLen);//程序在此处和
    
     if (len > 0)
     {
        [...]
    
        int number = clientNumber;
        pthread_create(&threadClient[clientNumber], 0, Receive, &number);
     }  // number gets destroyed here
    
    pthread_create(&threadClient[clientNumber], 0, Receive, &conn[clientNumber] );
    
    void* Receive(void* arg)
    {
       connection_t * conn = (connection_t *) arg; 
    
       [...]
    
       int r = read(conn->sock, &messageLen, sizeof(int));