Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets recvfrom重新读取套接字上的数据_Sockets_Unix_Udp_Recvfrom - Fatal编程技术网

Sockets recvfrom重新读取套接字上的数据

Sockets recvfrom重新读取套接字上的数据,sockets,unix,udp,recvfrom,Sockets,Unix,Udp,Recvfrom,我正在创建一个简单的服务器/客户端UDP套接字程序,但遇到了一个问题 问题是recvfrom()函数会不断重新读取上次发送的数据 因此,如果我从客户端向服务器发送两个数据包,那么recvfrom()将读取第一个数据包并打印其数据,然后它将不断地反复读取第二个数据包 据我所知,一旦执行了成功的读取操作,就应该将数据包从套接字中删除,但这似乎没有发生 我知道客户端没有重新发送数据,因为每当客户端发送数据时都会写入控制台输出 这是发送程序的函数 int sendPacket(int socketFd,

我正在创建一个简单的服务器/客户端UDP套接字程序,但遇到了一个问题

问题是recvfrom()函数会不断重新读取上次发送的数据

因此,如果我从客户端向服务器发送两个数据包,那么recvfrom()将读取第一个数据包并打印其数据,然后它将不断地反复读取第二个数据包

据我所知,一旦执行了成功的读取操作,就应该将数据包从套接字中删除,但这似乎没有发生

我知道客户端没有重新发送数据,因为每当客户端发送数据时都会写入控制台输出

这是发送程序的函数

int sendPacket(int socketFd, int type, char *typeString, char *data, int seq, int     windowSize, struct sockaddr_in serverName) {

    struct packet *sendPacketPtr, sendPacket;
    fd_set writeFdSet;

    sendPacketPtr = &sendPacket;

    sendPacket.flags = type;
    sendPacket.windowsize = windowSize;
    sendPacket.seq = seq;
    sendPacket.id = getpid();

    if (type == NORMAL)
        strcpy(sendPacket.data, data);

    FD_ZERO(&writeFdSet);
    FD_SET(socketFd, &writeFdSet);

    if(select(FD_SETSIZE, NULL, &writeFdSet, NULL, NULL) > 0) {
        if(sendto(socketFd, sendPacketPtr, sizeof(sendPacket), 0, (struct sockaddr     *)&serverName, sizeof(serverName)) < 0) {
            printf("%s packet was not sent\n", typeString);
            perror("Send error");
        } else {
            printf("%s packet was sent\n", typeString);
        }
    }

    return 0;
}
永远运行的输出(因为它一直在重新读取最后一个数据包)是:

  • 在故障情况下(即如果recvfrom或当select在超时时返回),您也返回未初始化的“缓冲区”,因此内容可以是先前的数据,但行为未定义。因此,在调用recvfrom之前,最好在开始时将其初始化为0(memset(&buffer,0,sizeof(struct packet)))

  • 在您正在检查的while循环中(receivedPacket.flags==NORMAL),如果正常
    然后,只有您正在打印缓冲区并再次调用该函数

    在“receivePacket”功能中,明确选择超时或recvfrom故障 将“receivedPacket.flags”更新为otherthen NORMAL,这样您就可以在执行循环时 休息


  • 在执行任何其他系统调用(如write())之前,必须先调用peror(),这是由printf()调用的。否则,errno值可能会更改,您会打印误导性的错误消息。我尝试了第二个答案,但没有成功。”Memsetting'buffer为0确实有效,同时也消除了我遇到的一些其他问题。谢谢这不是第二个答案,你需要注意上面提到的两点(1和2)
    for (int i = seqBase; i <= seqMax && i < packetNum; i++) {
          sendPacket(socketFd, NORMAL, "DATA", dataArray[i], i, 0, serverName);
    }
    
    struct packet receivePacket (int socketFd, struct sockaddr_in *address, int timeout,     int useTimeout) {
    
        struct packet buffer;
        fd_set readFdSet;
        struct sockaddr_in dest_addr;
    
        struct timeval selectTimeout;
        selectTimeout.tv_usec = 0;
        selectTimeout.tv_sec = timeout;
    
        FD_ZERO(&readFdSet);
        FD_SET(socketFd, &readFdSet);
    
        socklen_t len = sizeof(dest_addr);
    
        if(useTimeout == 0) {
            if(select(FD_SETSIZE, &readFdSet, NULL, NULL, NULL) > 0) {
                if(recvfrom(socketFd, &buffer, sizeof(buffer), 0, (struct sockaddr     *)&dest_addr, &len) < 0) {
                    perror("Read error");
                }else {
                    *address = dest_addr;
                }
            }
        }else {
            if(select(FD_SETSIZE, &readFdSet, NULL, NULL, &selectTimeout) > 0) {
                if(recvfrom(socketFd, &buffer, sizeof(buffer), 0, (struct sockaddr     *)&dest_addr, &len) < 0) {
                    perror("Read error");
                }else {
                    *address = dest_addr;
                }
            }
        }
    
        return buffer;
    
    }
    
    receivedPacket = receivePacket(socketFd, &destAddress, 0, 0);
    while (receivedPacket.flags == NORMAL) {
          printf("Data received: \"%s\", sequence: %d\n", receivedPacket.data, receivedPacket.seq);
          receivedPacket = receivePacket(socketFd, &destAddress, TIMEOUT, 1);
    }
    
    Data received: "Packet 0", sequence: 0
    Data received: "Packet 1", sequence: 1
    Data received: "Packet 1", sequence: 1
    Data received: "Packet 1", sequence: 1
    Data received: "Packet 1", sequence: 1
    ........