【问题标题】:Socket programming: recv/read issue套接字编程:recv/read 问题
【发布时间】:2010-03-01 05:15:15
【问题描述】:

编辑:以下代码已修复,可以正确接收和发送,并考虑发送和接收消息的实际字节数(后来感谢 EJP)

我在 Unix 中使用 C 编程。

我有应该交换消息的服务器和客户端。虽然客户端似乎可以正常发送消息,但服务器没有收到客户端发送的消息。我试过使用recv()read()(我知道它们实际上是一样的,但recv() 上有额外的标志)但我没有运气,我不确定问题到底是什么。

我在每次发送消息后将sleep(3) 放入客户端代码中,但我看到一旦客户端和服务器连接,服务器立即关闭而不等待传入消息。我做错了什么?

这是客户端代码:

#define SERVER_TCP_PORT 11112
#define MAX_DATA_SIZE   500

int main(int argc, char * argv[])
{
    int sockfd;
    char * host;
    char msg[MAX_DATA_SIZE];/* = "get my msg!\n";*/
    int msg_len;

    struct hostent * hp;
    struct sockaddr_in client_address, server_address;


    printf("y halo thar\n");


    // looking up from the host database
    if (argc == 2)
        host = argv[1];
    else
        exit(1);
    printf("sdf\n");


    hp = gethostbyname(host);
    if (!hp)
        exit(1);
    printf("host found\n");


    // setting up address and port structure information
    bzero((char * ) &server_address, sizeof(server_address)); // copy zeroes into string
    server_address.sin_family = AF_INET;
    bcopy(hp->h_addr, (char *) &server_address.sin_addr, hp->h_length);
    server_address.sin_port = htons(SERVER_TCP_PORT);
    printf("set\n");


    // opening up socket
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
        exit(1);
    printf("opened\n");


    // connecting
    if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0)
        exit(1);
    printf("connected\n");


    int i;

    for (i = 0; i < MAX_DATA_SIZE; ++i)
    {
        msg[i] = '.';
    }

    msg[MAX_DATA_SIZE-1] = '\0';

    for(i = 0; i < 11; i++)
    {
        // send message to connected socket
        msg_len = write(sockfd, msg, MAX_DATA_SIZE);
        if(msg_len < 1)
            printf("notsent\n");
        else
            printf("%i  bytes sent\n", msg_len);

        // recieve messages from connected socket
        msg_len = read(sockfd, msg, MAX_DATA_SIZE);
        if (msg_len < 1)
            printf("not recieved\n");
        else
        {
            printf("%i bytes received\n", msg_len);
            printf(msg);
            printf("\n");

        }
    }


    // close connection
    close(sockfd);
    printf("closed\n");

}

这是服务器端

#define SERVER_TCP_PORT 11112
#define MAX_DATA_SIZE   500


int main()
{

    printf("o halo thar\n");

    int sockfd, new_sockfd;
    int client_addr_len;
    char msg [MAX_DATA_SIZE];
    int msg_len;
    char got_msg [11] = "got ur msg\0";
    struct sockaddr_in server_address, client_address;


    // setting up address and port structure information
    bzero((char * ) &server_address, sizeof(server_address)); // copy zeroes into string
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = htonl(INADDR_ANY);
    server_address.sin_port = htons(SERVER_TCP_PORT);


    // opening up socket
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
        exit(1);
    printf("socket is opened\n");


    // binding
    if (bind(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0)
        exit(1);
    printf("socket is bound\n");


    // listening
    listen(sockfd,5);
    printf("listening\n");

    // block and wait for an incoming connection

    client_addr_len = sizeof(client_address);
    new_sockfd = accept(sockfd, (struct sockaddr *) &client_address, &client_addr_len);
    if (new_sockfd < 0)
        exit(1);

    printf("accepted\n");


    int i;

    for( i = 0; i < 11; i++)
    {
        // recieve messages from connected socket
        printf("waiting\n");
        msg_len = read(new_sockfd, msg, MAX_DATA_SIZE);
        if (msg_len < 1)
        {
            printf("no msg recieved\n");    
        }
        else
        {
            printf("bytes recieved: %i\n", msg_len);
        }


        // send message to connected socket
        msg_len = write(new_sockfd, got_msg, sizeof(got_msg));
        if (msg_len < 1)
            printf("not sent\n");
        else
            printf("%i bytes sent\n", msg_len);
    }


    // close connection
    close(sockfd);
    printf("socket closed. BYE! \n");


}

【问题讨论】:

    标签: c sockets recv


    【解决方案1】:

    在服务器代码中,问题出在这一行:

    msg_len = read(sockfd, msg, MAX_DATA_SIZE);
    

    您在sockfd 上调用read,但您需要在new_sockfdaccept() 返回的套接字)上调用readrecvnew_sockfd 是连接到客户端的那个(sockfd 用于接受进一步的连接 - 例如,如果另一个客户端连接)。

    【讨论】:

    • 感谢解决问题!!!是的,从 accept() 中读取新的套接字文件描述符更有意义。
    • 除了检查错误之外,您还忽略了 read() 和 write() 返回的计数。您不能这样做:您必须使用它们来确定实际读取或写入了多少数据。您不能假设您的请求已完全满足。
    • EJP 代码现在确实考虑了发送和接收的消息的实际字节数。谢谢。
    【解决方案2】:

    您应该从accept 返回的套接字中读取。

    尝试在从accept 返回的socket 上调用read

    【讨论】:

    • 客户端发送的消息明显是以'.'字符开头。
    【解决方案3】:

    接收方:

       while(1)
        {       
            len=read(sd,buff,sizeof(buff));
    
            if(len==0)
            {
                //End of File receving.             
    
                break;
            }
            else    
            {   
                st=fwrite(buff,sizeof(char),len,fp);
    
            }
        }
    

    【讨论】:

      【解决方案4】:

      发送方:

      while(!feof(fp))
      {
          len=fread(buff,sizeof(char),MW,fp);
          if(len==0)
          {
            //EOF
            st=write(cd,&d,sizeof(int));      
            break;
          }
          else
          {
              st=write(cd,buff,len);
          }
      }
      

      【讨论】:

        【解决方案5】:

        是基于流还是数据报的实现?

        您的操作流程存在一些问题。服务器可能会在客户端发送任何内容之前开始读取。

        由于客户端和服务器是分开的,您可以想象它们同时运行。 在您的服务器端“接受”连接请求之后,可能会发生一些握手开销或网络延迟导致服务器应用程序提前执行,尝试提取数据但遇到错误(尚未收到数据)。 您可以通过在接受连接后在服务器代码中添加睡眠来尝试这一点,客户端应该有足够的时间来发送数据。

        另一个更好的解决方案是让数据检索应对空缓冲区或异步读取。

        【讨论】:

        • 在客户端发送任何东西之前服务器调用read完全没有问题。 read 调用将简单地阻塞,直到数据可用。 “尚未收到数据”不是错误。
        • 而且也不需要睡觉。
        • 我只在客户端添加了 sleep() 来定位问题所在,但我真的不能(也不应该)使用 sleep(),因为这个程序的目的是测量包往返。
        猜你喜欢
        • 2013-11-06
        • 1970-01-01
        • 2021-10-29
        • 1970-01-01
        • 2013-06-09
        • 1970-01-01
        • 1970-01-01
        • 2022-10-06
        相关资源
        最近更新 更多