免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5575 | 回复: 7

[C] [求助]通过socket传输大文件问题(循环方法) [复制链接]

论坛徽章:
0
发表于 2009-04-14 18:10 |显示全部楼层
5可用积分
client向server上传文件, 用的循环方法,但是始终只有一个BUFSIZE大小的字符串写入outfile,还请帮忙看看是什么地方不对,还是我对socket理解本身存在问题?
  P.s 还有个支持断点续传的要求, 也请各位指点一下思路, 谢谢。

//client.c

#include <stdio.h>     
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>  
#include <string.h>
#include <unistd.h>

#define BUFSIZE 1024

void DieWithError(char *errorMessage);

int main(int argc, char *argv[])
{
    int sock;                     
    struct sockaddr_in ServAddr;
    unsigned short ServPort;       
    char *servIP;              
    char RdBuffer[BUFSIZE];
    int i, length, cnt = 0;
    FILE *ifp;
       
    if ((argc < 3) || (argc > 4))        {          
       fprintf(stderr, "Usage: %s <File Name> <Server IP> [<Echo Port>]\n", argv[0]);
       exit(1);
    }

    servIP = argv[2];

    if (argc == 4)
        ServPort = atoi(argv[3]);
    else
        ServPort = 3333;

    if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
        DieWithError("socket() failed");

    memset(&ServAddr, 0, sizeof(ServAddr));     
    ServAddr.sin_family = AF_INET;            
    ServAddr.sin_addr.s_addr = inet_addr(servIP);
    ServAddr.sin_port = htons(ServPort);                

    if (connect(sock, (struct sockaddr *) &ServAddr, sizeof(ServAddr)) < 0)
        DieWithError("connect() failed");

    if ((ifp = fopen(argv[1], "r")) == NULL)       
        DieWithError("file open error\n");
               
    fseek(ifp, 0, SEEK_END);
    length = ftell(ifp);
    fseek(ifp, 0, SEEK_SET);
       
    if ((length % BUFSIZE) == 0)
        cnt = length / BUFSIZE;
    else
        cnt = length / BUFSIZE + 1;

    for (i = 0; i < cnt; i++)        {
        memset(RdBuffer, '\0', BUFSIZE);
        fread(RdBuffer, BUFSIZE, 1, ifp);
    if (send(sock, RdBuffer, BUFSIZE, 0) < 0)
        DieWithError("send() failed");
    printf("%s\n", RdBuffer);               
    }

    fclose(ifp);
    close(sock);
    exit(0);
}

void DieWithError(char *errorMessage)        {               
    perror(errorMessage);
    exit(1);
}




//server.c

#include <stdio.h>     
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>   
#include <string.h>  
#include <unistd.h>

#define MAXPENDING 5  
#define BUFSIZE 1024  

void DieWithError(char *errorMessage);

int main(int argc, char *argv[])
{
    int servSock;                  
    int clntSock;                               
    struct sockaddr_in ServAddr;
    struct sockaddr_in ClntAddr;
    unsigned short ServPort;   
    unsigned int clntLen;     
    char WrBuffer[BUFSIZE];
    FILE *ofp;

    if (argc != 2)        {   
            fprintf(stderr, "Usage:  %s <Server Port>\n", argv[0]);
        exit(1);
    }

    ServPort = atoi(argv[1]);  

    if ((servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
        DieWithError("socket() failed");
      
    memset(&ServAddr, 0, sizeof(ServAddr));       
    ServAddr.sin_family = AF_INET;               
    ServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    ServAddr.sin_port = htons(ServPort);             

    if (bind(servSock, (struct sockaddr *) &ServAddr, sizeof(ServAddr)) < 0)
        DieWithError("bind() failed");
    if (listen(servSock, MAXPENDING) < 0)
        DieWithError("listen() failed");

    for (; ; )        {
        ofp = fopen("outfile", "a");
        clntLen = sizeof(ClntAddr);
        if ((clntSock = accept(servSock, (struct sockaddr *) &ClntAddr, &clntLen)) < 0)
            DieWithError("accept() failed");
        printf("Handling client %s\n", inet_ntoa(ClntAddr.sin_addr));

        memset(WrBuffer, '\0', BUFSIZE);
        if (((recv(clntSock, WrBuffer, BUFSIZE, 0))) < 0)
            DieWithError("recv() failed");
        if (fwrite(WrBuffer, BUFSIZE, 1, ofp) < 0)
            DieWithError("write error\n");
        printf("%s\n", WrBuffer);
        fclose(ofp);
        }
    return 0;
}

void DieWithError(char *errorMessage)        {
    perror(errorMessage);
    exit(1);
}

最佳答案

查看完整内容

if (((recv(clntSock, WrBuffer, BUFSIZE, 0))) < 0) DieWithError("recv() failed"); if (fwrite(WrBuffer, BUFSIZE, 1, ofp) < 0) DieWithError("write error\n"); printf("%s\n", WrBuffer);->while (1){ if (((recv(clntSock, WrBuffer, BUFSIZE, 0))) < 0) {DieWithError("recv() failed");break;} if (fwrite(WrBuffer, BUFSIZE, 1, ofp) < 0) {DieWithEr ...

论坛徽章:
0
发表于 2009-04-14 18:10 |显示全部楼层
if (((recv(clntSock, WrBuffer, BUFSIZE, 0))) < 0)
            DieWithError("recv() failed");
        if (fwrite(WrBuffer, BUFSIZE, 1, ofp) < 0)
            DieWithError("write error\n");
        printf("%s\n", WrBuffer);

->

while (1)
{
        if (((recv(clntSock, WrBuffer, BUFSIZE, 0))) < 0)
            {DieWithError("recv() failed");break;}
        if (fwrite(WrBuffer, BUFSIZE, 1, ofp) < 0)
            {DieWithError("write error\n");break;}
        printf("%s\n", WrBuffer);;
}

论坛徽章:
5
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:53:172015亚冠之水原三星
日期:2015-06-02 16:34:202015年亚冠纪念徽章
日期:2015-10-19 18:13:37程序设计版块每日发帖之星
日期:2015-11-08 06:20:00
发表于 2009-04-14 18:56 |显示全部楼层
客户端怎么不用sendfile

接收文件的话,下面代码这么写就决定了每次只能接收一点数据啊.
    for (; ; )        {
        ofp = fopen("outfile", "a");
        clntLen = sizeof(ClntAddr);
        if ((clntSock = accept(servSock, (struct sockaddr *) &ClntAddr, &clntLen)) < 0)
            DieWithError("accept() failed");
        printf("Handling client %s\n", inet_ntoa(ClntAddr.sin_addr));

        memset(WrBuffer, '\0', BUFSIZE);
        if (((recv(clntSock, WrBuffer, BUFSIZE, 0))) < 0)
            DieWithError("recv() failed");
        if (fwrite(WrBuffer, BUFSIZE, 1, ofp) < 0)
            DieWithError("write error\n");
        printf("%s\n", WrBuffer);
        fclose(ofp);
        }

一般都是这样的流程
打开文件,接受连接,在新的套接字上,循环recv数据并写入到文件.

[ 本帖最后由 xinglp 于 2009-4-14 19:00 编辑 ]

论坛徽章:
0
发表于 2009-04-14 20:52 |显示全部楼层
server只recv一次,之后阻塞在accept上了,

论坛徽章:
0
发表于 2009-04-15 13:18 |显示全部楼层
我也感觉主要是block的问题,和用send/sendfile应该没太大关系。那么解决这类问题一般用什么方法呢?
初学socket,还请指点下。

论坛徽章:
0
发表于 2009-04-15 13:29 |显示全部楼层
原帖由 deanreal 于 2009-4-15 13:18 发表
我也感觉主要是block的问题,和用send/sendfile应该没太大关系。那么解决这类问题一般用什么方法呢?
初学socket,还请指点下。


前面几位老兄都已经讲得很清楚了, recv 和 fwrite 要放在一个循环里面去做, 直到文件接收完毕(客户端断开). 因为不能保证服务器一次recv就把整个文件的数据都收完了.
写客户端的时候你不也知道要把 fread 和 send 放在一个循环里面去做吗?

论坛徽章:
0
发表于 2009-04-15 14:28 |显示全部楼层
原帖由 cskyrain 于 2009-4-14 20:52 发表
server只recv一次,之后阻塞在accept上了,

正解

论坛徽章:
0
发表于 2009-04-15 14:31 |显示全部楼层
其实办法多的很啊,接口控制
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP