首页 文章

C语言中的套接字通信 . 发送文件内容

提问于
浏览
-2

所以前几天我得到了一个相对简单的任务,即构建一些客户端和一些服务器代码,服务器在这些代码中收到消息并返回当前系统时间 . 这并不难,我交付并获得了一个简单的标记 .

我开始考虑更多,我决定出发并尝试发送特定文件 server --> client 的内容(服务器将内容发送到客户端) . 当我构建我经常在本地测试的代码时,它按预期工作,当我将服务器代码上传到运行Ubuntu的服务器(hah)时出现了真正的问题 . 启动服务器,一切正常,启动客户端,要求"index.html"和 BAM! 一半文件没有收到 . 服务器打印它(我做了它所以打印文件的内容,因为它发送,所以我可以更轻松地排除故障) .

我现在一直在寻找,每当我找到一些看起来很有用的东西时,它会以不同的编程语言结束,并且无法在C中找到任何等价物 .

在客户端和服务器代码中使用sleep似乎解决了这个问题,但我认为这不是一个好习惯 .

代码是乱七八糟的,所以我将包括我认为相关的内容,我还将包含一个完整代码的链接 . 我真的打算改进它,但是在尝试解决这个问题时失去了动力,我只是让它变得更糟 .

Client side

printf("Please specify the filename: ");
fgets(msg,1000,stdin); // get message from std input

if(strcmp(msg,"\n")==0) {
    printf("Wrong file name or format\n");
    printf("Please specify the filename: ");
    fgets(msg,1000,stdin); // get message from std input
}


while(strcmp(msg,"!stop\n")) {

    msg[strlen(msg)-1]='\0';
    write(sockfd,msg,strlen(msg));
    FILE *fp = NULL;

    char filecontent[1000];
    bzero(filecontent,sizeof(filecontent));


    while(  (n = read(sockfd,filecontent,1000)) && strcmp(filecontent,"Over and out!")!=0  ) {

        if(strcmp(filecontent,"No such file")!=0 && fp == NULL) {
            fp = fopen(msg,"w");
        }

        printf("%s",filecontent);

        if(fp !=NULL)
            fprintf(fp, "%s",filecontent);

        bzero(filecontent,sizeof(filecontent));
    }

    if(fp != NULL)
        fclose(fp);

    printf("\nPlease specify the filename: ");
    fgets(msg,1000,stdin); // get message from std input


    if(strcmp(msg,"\n")==0) {
        printf("Wrong file name or format\n");
        printf("Please specify the filename: ");
        fgets(msg,1000,stdin); // get message from std input
    }

}

Server side

char date[50];
time_t ticks;
struct tm *tinfo;
time(&ticks);
tinfo=localtime(&ticks);
strcpy(date,asctime(tinfo));
printf("DATA: %s\n",date);
write(newsocketfd,date,sizeof(date));

while( (n = read(newsocketfd,msg,1000)) && strcmp(msg,"!stop\n")!=0) {
    //printf("MSG: %s\n",msg);

    if(n<0)
        error("ERROR READING");
    /////////READING FILE/////////////


    char *filename = malloc(sizeof(msg)+1);
    strcpy(filename,msg);
    printf("'server filename:%s'\n",filename);
    FILE *fp = fopen( filename,"r");

    if(fp == NULL) {
        printf("No such file found\n");
        write(newsocketfd,"No such file",sizeof("No such file"));
    }

    while( fp!=NULL && fgets(msg,1000,fp)!=NULL){
        write(newsocketfd,msg,sizeof(msg));
        msg[strlen(msg)-1]='\0';
        printf("server: '%s'\n",msg);
        bzero(msg,sizeof(msg));

    }


bzero(msg,sizeof(msg));
bzero(filename,strlen(filename));
n = write(newsocketfd,"Over and out!",sizeof("Over and out!"));
printf("Over\n");

}

对任何头痛都很抱歉 . Full code here.

Examples:

I think this pretty much shows the problem

我的想法是,服务器逐行读取文件,并逐行将其发送到客户端,当服务器发送“over”并且客户端从那里停止读取时,似乎客户端从不接收所有信息或“结束”信号 . 值得补充的是,如果我在本地计算机上运行这两个代码,这个工作完全正常 .

1 回答

  • 0

    欢迎来到网络编程世界!出于某种原因,网络协议是分层的 . 当您在TCP套接字上发送内容并立即关闭套接字时,传递是不可靠的:它可能正确传递给对等方,或者可能因竞争条件而消失 .

    唯一可靠的方法是仅在对等方发送确认可以接收已发送的所有内容时关闭套接字 . 标准协议使用控制消息,您真的应该考虑这一点,但如果您不需要警告服务器发生客户端故障,您可以让客户端在收到 "Over and out!" 时关闭连接 . 顺便说一句,你应该知道,由于TCP是一种流协议,没有什么能保证消息不会被分割成多个读取,或者连接到其他字节 . 所以你应该保持前一次读取的结束(信号字符串的大小减去一个字节),连接下一次读取并在缓冲区中的任何地方搜索字符串 .

    另一种常见的方法是使用graceful shutdown:发送方使用 shutdown(socket.SHUT_WR) 来通知通信已经结束而不关闭套接字并等待(使用 read )对等方在一切正确传递时关闭套接字 .

相关问题