【问题标题】:c - client server communication via socket in infinite loopc - 通过无限循环中的套接字进行客户端服务器通信
【发布时间】:2014-08-27 06:40:44
【问题描述】:

我有下面的代码用于客户端页面和服务器页面,我想为此从客户端向服务器端发送五条消息(无论如何,对于这个初始测试)。如果我不把它放在一个循环中,代码就可以正常工作,但是我只能在客户端和服务器关闭之前发送一条消息。当我将代码放入循环中时,它似乎陷入了某种死锁。我得到的结果下面是代码。我尝试了各种更改并进行了广泛的研究,但无法使其发挥作用。提前感谢您提供的任何解决方案。

服务器端结果

./服务器 5000

这是消息:测试

客户端结果

./client localhost 5000

请输入消息:test

我收到了你的消息

请输入消息:另一个测试

请输入信息:再次测试

请输入信息:再次测试

// 服务器停止确认收到消息,我必须不断重置客户端和服务器

服务器.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

int main(int argc, char *argv[])
{
    int sockfd, newsockfd, portno, clilen;
    char buffer[256];
    struct sockaddr_in serv_addr, cli_addr;
    int n;
    if (argc < 2) {
        printf("Need at least two arguments\n");
        exit(1);
    }
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) 
        printf("ERROR opening socket\n");
    bzero((char *) &serv_addr, sizeof(serv_addr));
    portno = atoi(argv[1]);
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(portno);
    if (bind(sockfd, (struct sockaddr *) &serv_addr,
         sizeof(serv_addr)) < 0) 
    printf("ERROR on binding\n");
    listen(sockfd,atoi(argv[1]));
    clilen = sizeof(cli_addr);
    while ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen)) >= 0) {
        if (newsockfd < 0) 
            printf("ERROR on accept\n");
        bzero(buffer,256);
        n = read(newsockfd,buffer,255);
        if (n < 0) printf("ERROR reading from socket\n");
        printf("Here is the message: %s\n",buffer);
        n = write(newsockfd,"I got your message\n",18);
        if (n < 0) printf("ERROR writing to socket\ns");
    }
    close(sockfd);
    return 0;
}

client.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

int main(int argc, char *argv[]) {
    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;
    char buffer[256];
    if (argc < 3) {
        printf("Not enough arguments\n");
        exit(0);
    }
    portno = atoi(argv[2]);
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
        printf("Error opening socket\n");
    server = gethostbyname(argv[1]);
    if (server == NULL) {
        printf("Error: no such host\n");
        exit(0);
    }
    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    bcopy((char *)server->h_addr,
          (char *)&serv_addr.sin_addr.s_addr,
          server->h_length);
    serv_addr.sin_port = htons(portno);
    if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
        printf("Error connecting\n");
    int i = 0;
    while (i < 5) {
        printf("Please enter the message: ");
        bzero(buffer, 256);
        fgets(buffer, 255, stdin);
        n = write(sockfd, buffer, strlen(buffer));
        if (n < 0)
            printf("Error writing to socket");
        bzero(buffer, 256);
        n = read(sockfd, buffer, 255);
        if (n < 0)
            printf("Error reading from socket");
        printf("%s\n", buffer);
        i++;
    }
    close(sockfd);
    return 0;
}

【问题讨论】:

  • 那么您的服务器将接受并回答 1 条消息,然后阻止 accept 等待另一个永远不会出现的客户端连接。
  • 您没有使用 read 的返回值来确定读取了多少字节。

标签: c sockets client-server port


【解决方案1】:

在接受另一个连接之前,您需要重组代码以处理您拥有的一个连接。这是很糟糕的代码,但却是您想要做的事情的基本模板。即便如此,您一次也不能处理多个连接。您必须多路复用或线程。此外,始终在循环中读/写,因为不能保证在任何一次调用中都能获得完整的请求。了解和使用perror或兄弟。

void do_stuff(int sock)
{
    for (int i = 0; i < 5; ++i)
    {

        bzero(buffer, 256);

        n = read(newsockfd, buffer, 255);

        if (n < 0)
            printf("ERROR reading from socket\n");

        printf("Here is the message: %s\n", buffer);

        n = write(newsockfd, "I got your message\n", 18);

        if (n < 0)
            printf("ERROR writing to socket\ns");
    }
}


while ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen)) >= 0)
{
    if (newsockfd < 0)
        printf("ERROR on accept\n");

    do_stuff(newsockfd);

    close(newsockfd);
}

【讨论】:

    【解决方案2】:

    我知道为时已晚。但是对于可能有同样疑问的人,我试图回答这个问题。

    回答
    把服务器程序改成这个怎么样

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h> 
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <unistd.h>
    
    int main(int argc, char *argv[])
    {
        int sockfd, newsockfd, portno, clilen;
        char buffer[256];
        struct sockaddr_in serv_addr, cli_addr;
        int n;
        if (argc < 2) {
            printf("Need at least two arguments\n");
            exit(1);
        }
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0) 
            printf("ERROR opening socket\n");
        bzero((char *) &serv_addr, sizeof(serv_addr));
        portno = atoi(argv[1]);
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = INADDR_ANY;
        serv_addr.sin_port = htons(portno);
        if (bind(sockfd, (struct sockaddr *) &serv_addr,
                    sizeof(serv_addr)) < 0) 
            printf("ERROR on binding\n");
        listen(sockfd,atoi(argv[1]));
        clilen = sizeof(cli_addr);
        while ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen)) >= 0) {
            if (newsockfd < 0) 
                printf("ERROR on accept\n");
            bzero(buffer,256);
            while(true)
            {   
                n = read(newsockfd,buffer,255);
                if (n < 0)
                {
                    printf("ERROR reading from socket\n");
                    break;
                }           
                printf("Here is the message: %s\n",buffer);
                n = write(newsockfd,"I got your message\n",18);
                if (n < 0)
                {
                    printf("ERROR writing to socket\ns");
                    break;
                }
            }
            close(newsockfd);
        }
        close(sockfd);
        return 0;
    }  
    

    这是更改的部分。我稍微更改了代码,以便在发生任何写入或读取错误时关闭连接。

    while ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen)) >= 0) {
        if (newsockfd < 0) 
            printf("ERROR on accept\n");
        bzero(buffer,256);
        while(true)
        {   
            n = read(newsockfd,buffer,255);
            if (n < 0)
            {
                printf("ERROR reading from socket\n");
                break;
            }           
            printf("Here is the message: %s\n",buffer);
            n = write(newsockfd,"I got your message\n",18);
            if (n < 0)
            {
                printf("ERROR writing to socket\ns");
                break;
            }
        }
        close(newsockfd);
    }
    

    【讨论】:

      猜你喜欢
      • 2018-06-30
      • 2012-04-21
      • 1970-01-01
      • 2012-08-30
      • 2012-11-02
      • 2019-08-03
      • 2017-08-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多