即使客户端没有发送任何内容,recvfrom()也会获得空缓冲区

时间:2015-11-22 06:52:54

标签: c sockets udp datagram

client:argv [1]:ip address,argv [2]:端口号,argv [3]:文件名 客户端首先将argv [3]发送到服务器,然后以UDP连接的形式发送文件。一旦发现没有数据读取,它就会从循环中退出并终止。

server:argv [1]:端口号 这是迭代的,所以重复接收永远直到系统得到^ C.首先是接收文件名并进入循环以获取数据。实际上我仍然不知道我对逃脱条件做了什么。我认为当最后一个数据包大小与BUFFER_SIZE相同时会产生一些问题。无论如何它到目前为止没有问题,所以这部分不是最重要的任务。

我遇到的问题是接收文件名的recvfrom()获取空数据。我所期望的是该函数等待从客户端发送文件名。下面添加了两个源代码和终端上显示的结果。任何人都可以帮我阻止recvfrom()获取空缓冲区吗?

SERVER:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <arpa/inet.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <fcntl.h>

#define BUFFER_SIZE 50

int main(int argc, char *argv[]){
    int sockfd;//socket file descriptor
    int byteRcvd;//gets received bytes when recvfrom() is called
    int addr_size = sizeof(struct sockaddr);//used to bind
    int fp;//to handle file
    int i;

    struct sockaddr_in addr;//contains address information

    char fileName[20];//gets file name
    char buf[BUFFER_SIZE];//buffer

    //create a socket
    sockfd = socket(PF_INET, SOCK_DGRAM, 0);

    //set and addr
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);//address here
    addr.sin_port = htons(atoi(argv[1]));//port # here
    bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));

    //repetition of receiving files
    while(1){
        //get file name and open
        memset(buf, 0, sizeof(buf));
        byteRcvd = recvfrom(sockfd, buf, sizeof(buf), 0,
            (struct sockaddr*)&addr, &addr_size);
        fp = open(buf, O_RDWR | O_CREAT, 0644);
            printf("file \"%s\" is opened\n", buf);

        //get file
        memset(buf, 0, sizeof(buf));//reset buffer
        //byteRcvd = recvfrom(sockfd, buf, sizeof(buf), 0,
            //(struct sockaddr*)&addr, &addr_size);

        byteRcvd = BUFFER_SIZE;
        while(byteRcvd){
            if(byteRcvd != BUFFER_SIZE)
                break;

            //rcv data and show its size
            if((byteRcvd = recvfrom(sockfd, buf, sizeof(buf), 0,
                (struct sockaddr*)&addr, &addr_size)) == EOF){
                printf("Out of loop by EOF\n");
                break;
            }
            printf("%dB Rcvd ", byteRcvd);

            //printf rcvd data
            for(i = 0; i < BUFFER_SIZE; i++)
                if(buf[i] == '\n')
                    printf("#", buf[i]);
                else
                    printf("%c", buf[i]);

            printf("\n");
            //getchar();

            write(fp, buf, byteRcvd);

            memset(buf, 0, sizeof(buf));
        }
        printf("byteRcvd: %d\n", byteRcvd);

        close(sockfd);
        close(fp);
        fp = 0;

        printf("Continue??\n");
        getchar();
    }
    return 0;
}

客户端:

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

#define BUFFER_SIZE 50

int sockfd;//socket file descriptor
struct sockaddr_in addr;//variable to contain IPv4 and port#

//argv[1]: IP address
//argv[2]: port #
//argv[3]: file name to be sent
int main(int argc, char *argv[]){
    int i, n;
    int byteSent = 0;//size of data sent at each time
    int addr_size = sizeof(struct sockaddr);

    int fp = open(argv[3], O_RDONLY);

    char buf[BUFFER_SIZE];//buffer to contain data
    char temp[BUFFER_SIZE];

    //check argument number
    if(argc != 4)
        exit(1);

    //create a socket
    if((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
        exit(1);

    //set addr
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(argv[1]);
    addr.sin_port = htons(atoi(argv[2]));

    //send the file name to the server
    byteSent = sendto(sockfd, argv[3], sizeof(argv[3]), 0,
        (struct sockaddr*)&addr, addr_size);

    memset(buf, 0, sizeof(buf));

    //while((byteSent = read(fp, buf, BUFFER_SIZE))){
        byteSent = read(fp, buf, BUFFER_SIZE);
    while(byteSent){
        getchar();
        sendto(sockfd, buf, byteSent, 0,
            (struct sockaddr*)&addr, addr_size);
        printf("%d byte sent\n", byteSent);
        for(i = 0; i < BUFFER_SIZE; i++){
            if(i == 0)
                printf("[");
            if(buf[i] == '\n')
                printf("@");
            else
                printf("%c", buf[i]);
            if(i == 39)
                printf("]");}
        printf("\n");
        memset(buf, 0, sizeof(buf));
        byteSent = read(fp, buf, BUFFER_SIZE);
        printf("Next byteSent is to be %d\n", byteSent);
    }

    close(sockfd);
    close(fp);
    return 0;
}

l.txt:

Lorem ipsum dolor sit amet,consectetur adipiscing elit,sed do eiusmod tempor incididunt ut labore et dolore magna aliqua。 Ut enim ad minim veniam,quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat。 Duis aute irure dolor in repreptderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur。 Excepteur sint occaecat cupidatat non proident,sunt in culpa qui officia deserunt mollit anim id est laborum。

服务器终端:

[21100610@localhost server]$ ./s 70000
file "l.txt" is opened
50B Rcvd Lorem ipsum dolor sit amet, consectetur adipiscing
50B Rcvd  elit, sed do eiusmod tempor incididunt ut labore
50B Rcvd et dolore magna aliqua. Ut enim ad minim veniam, q
50B Rcvd uis nostrud exercitation ullamco laboris nisi ut a
50B Rcvd liquip ex ea commodo consequat. Duis aute irure do
50B Rcvd lor in reprehenderit in voluptate velit esse cillu
50B Rcvd m dolore eu fugiat nulla pariatur. Excepteur sint
50B Rcvd occaecat cupidatat non proident, sunt in culpa qui
46B Rcvd  officia deserunt mollit anim id est laborum.#
byteRcvd: 46
Continue??   <=== at this point I typed enter

file "" is opened
Out of loop by EOF
byteRcvd: -1
Continue??   <=== at this point I typed enter

file "" is opened
Out of loop by EOF
byteRcvd: -1
Continue??   <=== at this point I typed enter

file "" is opened
Out of loop by EOF
byteRcvd: -1
Continue??
^C
[21100610@localhost server]$

客户终端:

[21100610@localhost client]$ ./c 127.0.0.1 70000 l.txt

50 byte sent
[Lorem ipsum dolor sit amet, consectetur ]adipiscing
Next byteSent is to be 50

50 byte sent
[ elit, sed do eiusmod tempor incididunt ]ut labore
Next byteSent is to be 50

50 byte sent
[et dolore magna aliqua. Ut enim ad minim] veniam, q
Next byteSent is to be 50

50 byte sent
[uis nostrud exercitation ullamco laboris] nisi ut a
Next byteSent is to be 50

50 byte sent
[liquip ex ea commodo consequat. Duis aut]e irure do
Next byteSent is to be 50

50 byte sent
[lor in reprehenderit in voluptate velit ]esse cillu
Next byteSent is to be 50

50 byte sent
[m dolore eu fugiat nulla pariatur. Excep]teur sint
Next byteSent is to be 50

50 byte sent
[occaecat cupidatat non proident, sunt in] culpa qui
Next byteSent is to be 46

46 byte sent
[ officia deserunt mollit anim id est lab]orum.@
Next byteSent is to be 0
[21100610@localhost client]$

1 个答案:

答案 0 :(得分:2)

这里有问题吗?

在收到少于50个字节的数据包之前,调用recvfrom接收文件内容。当发生这种情况时,关闭套接字并循环返回尝试读取更多数据(另一个文件?),但recvfrom将始终返回-1(错误)EBADF,因为套接字已关闭

您正在比较recvfromEOF的返回值,这是无意义的 - EOF适用于&lt; stdio.h&gt;函数,而不是套接字函数。恰好EOF为-1,套接字函数返回-1表示错误,因此通过检查EOF,您实际上是在检查错误...