【问题标题】:Data is not received correctly from TCP socket using C [closed]未使用 C 从 TCP 套接字正确接收数据 [关闭]
【发布时间】:2012-10-12 11:19:42
【问题描述】:

我使用的是 Ubuntu 12.04 32 位版本 我编写了一个程序来接收来自 TCP 客户端的 XML 文件。 同一个程序也通过 unix 域套接字从另一个进程接收数据。 为此,我正在使用 poll() 系统调用。

我的问题是,有时我没有正确获取 XML 数据,或者有时它也丢失了。但是由于我使用的是 TCP,如果有数据丢失客户端会知道。但客户端没有显示任何错误。谁能告诉我为什么会这样?

我可以提供一些代码:

int config_server_tcp(int 端口) { int sockfd = -1; 结构 sockaddr_in my_addr; // 我的地址信息 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket() 失败。"); } 别的 { my_addr.sin_family = AF_INET; my_addr.sin_port = htons(port); my_addr.sin_addr.s_addr = htonl(INADDR_ANY); //自动填写我的IP memset(&(my_addr.sin_zero), 0, 8); // 将结构的其余部分归零 if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { perror("绑定() 失败。"); } 别的 { if (听 (sockfd, 8) == -1) { perror("listen() 失败。"); } } } 返回 sockfd; } int send_to_tcp_server(unsigned char * message, int size, char * server_ip, int port) { int sockfd; 结构 sockaddr_in their_addr; 整数字节 = -1; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket() 失败。"); } 别的 { 他们的地址.sin_family = AF_INET; their_addr.sin_port = htons(port); their_addr.sin_addr.s_addr=inet_addr(server_ip); memset(&(their_addr.sin_zero), '\0', 8); // 将结构的其余部分归零 if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof (their_addr)) == -1) { perror("connect() 失败。"); } 别的 { if ((numbytes=send(sockfd , message, size, 0)) == -1) { printf ("发送失败。\n"); } } 关闭(sockfd); } 返回字节数; } void process_tcp (int sock) { 结构 sockaddr_in their_addr; // 说话者的地址信息 int 收到; socklen_t addr_len; 字符缓冲区[BUFF_SIZE]; addr_len = sizeof (their_addr); int clientfd = 接受 (sock, (struct sockaddr *)&their_addr, &addr_len); 如果 (clientfd == -1) { perror("accept() 失败。"); } 别的 { 做 { 收到 = recv(clientfd, 缓冲区, BUFF_SIZE, 0); 如果(收到 == -1) { perror("recv() 失败。"); 休息; } 别的 { //做点什么 } } 而(收到!= 0); 关闭(clientfd); } }

循环调用进程TCP函数

【问题讨论】:

  • 请出示您的代码,很可能您将 TCP 视为数据报协议(这是错误的),但我们不能说没有代码。
  • 错误几乎肯定在你用//do something替换的代码中。
  • 您上面的代码缺少组装消息的代码和对整个消息执行某些操作的代码。您已用//do something 替换的汇编代码,以及对消息执行某些操作的代码必须在while 循环结束之后进行(因为连接的关闭是您指示应用程序结束的方式-级消息)。缺少代码中最关键的两个部分。
  • @Hari:可能是这样。那是那里最关键的代码。这就是您必须实际实现“基于 TCP 的 XML”协议的地方。该错误很可能出现在您的“XML over TCP”协议设计或实现中。
  • @KarolyHorvath:他发布了他的代码。他就是这样做的。 if ((numbytes=send(sockfd , message, size, 0)) == -1) { printf ("Sending failed.\n"); } } close (sockfd);

标签: c linux sockets tcp


【解决方案1】:

几乎可以肯定,错误出现在您未显示的代码中,该代码根据您的 XML-over-TCP 协议组装应用程序级消息。这是一种方法:

void process_tcp (int sock)
{
    struct sockaddr_in their_addr;
    int received, total_received;
    socklen_t addr_len;
    char buffer[BUFF_SIZE];

    addr_len = sizeof (their_addr);
    int clientfd = accept (sock, (struct sockaddr *)&their_addr, &addr_len);
    if (clientfd == -1)
    {
        perror("accept() failed.");
    }       
    else
    {
        total_received = 0;
        do
        {
            received = recv(clientfd, buffer + total_received,
                            BUFF_SIZE - total_received, 0);
            if (received == -1) 
            {
                perror("recv() failed.");
                break;
            }
            if (received > 0)
                total_received += received;
        }
        while (received != 0);
        buffer[total_received] = 0;
        // here we can do something with 'buffer'              
        close (clientfd);
    }
}

请注意,缺少很多错误检查。

【讨论】:

  • 谢谢大卫。我会试试这个代码。
  • 对不起,仍然没有收到正确的数据。
  • 你能描述一下它正在接收什么以及以什么方式不正确吗?
  • 好的。前两次我以 10 秒的间隔发送了 XML,它正在接收没有任何错误。之后,我以大约 1 秒的间隔发送它,它接收到部分数据,然后是最后一部分数据,然后是中间部分。正如我在问题中所说,我在 poll() 的帮助下同时从 UNIX domail 套接字接收。这会导致什么吗?
  • 哦,我想我知道它是什么了。您的套接字是非阻塞的,对吗?如果是这样,您需要每个套接字应用程序消息缓冲区。否则,您将无处组装应用程序消息。我上面的代码可以很好地阻塞套接字。但是对于非阻塞的,你需要将应用层的协议状态保存在某个地方。
猜你喜欢
  • 2012-02-10
  • 2014-10-05
  • 2018-12-14
  • 2012-12-28
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 2021-06-13
相关资源
最近更新 更多