New Document
     寄存器


<<  < 2007 - >  >>
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30


公告
★★★★★★★★★★★★★★★
    一位将军说,对对手的最好惩罚,就是让自己变得比他更强。我会一直努力!
QQ:82314377
E-mail:chen.brick@gmail.com
★★★★★★★★★★★★★★★

我的分类(专题)

日志更新

最新评论

留言板

链接
处理 SSI 文件时出错

Blog信息
  • 日志:86
  • 评论:67
  • 留言:13
  • 访问:







WinSock实现网络文件传输程序
brick 发表于 2007-4-1 1:19:00

/*
 * WinSock实现网络文件传输程序
 * Windows 2003 + Visual C++ 6.0 编译通过
 * brick 2007.4.1
 */
///////////////////////////////////////////////////////////////////////////////
#pragma comment(lib, "ws2_32.lib")
#i nclude<stdio.h>
#i nclude<string.h>
#i nclude<winsock2.h>
#i nclude<windows.h>
#i nclude<assert.h>

#define CHARLENGTH 80 //字符串长//
#define SEND_BUFFER_SIZE 1024 //发送缓冲区//
#define RECV_BUFFER_SIZE 1024 //接收缓冲区//
#define PORT 8508 //默认端口//
#define TRUE 1
#define FALSE 0

enum {CMD_NAME};

int RecvFile(); //接收
int SendFile(); //发送
int usage(char msg[]); //帮助提示

int main(int argc, char *argv[]) {

    char operate[CHARLENGTH];
    memset(operate, '\0', sizeof(operate));
    usage(argv[CMD_NAME]);

    while (printf("\n\n") && printf("请输入参数 : ") && scanf("\n%s", operate) != EOF) {
            if (strlen(operate) > 2 ) {
            usage(argv[CMD_NAME]);
            continue;
        }
        switch (operate[1]) {
            case 'r': RecvFile(); break;
            case 's': SendFile(); break;
            case 'q': printf("谢谢使用 [%s]\nByeBye!\n\n", argv[CMD_NAME]); return(0); break;
            default : usage(argv[CMD_NAME]); break;
        }
    }

    return(0);
}

///////////////////////////////////////////////////////////////////////////////
//接收函数
int RecvFile() {

    char filePath[CHARLENGTH];

    printf("请输入保存文件的绝对路径 :\n"); //获取文件保存路径//
    memset(&filePath, '\0', sizeof(filePath));
    scanf("\n%s", filePath);

    WSADATA wsaData;
    WSAStartup(WINSOCK_VERSION, &wsaData);

    //建立连接//
    ///////////////////////////////////////////////////////////////////////////
    SOCKET sockrecv = socket(AF_INET, SOCK_STREAM, 0); //创建套接字//

    if (sockrecv < 0) {
        closesocket(sockrecv);
        WSACleanup();
        perror("sock");
        printf("警告: 创建套接字失败!\n");
        return(FALSE);
    }
   
    SOCKADDR_IN addrSrv;
    memset(&addrSrv, '\0', sizeof(addrSrv));
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //填充本地ip//
    addrSrv.sin_port = htons(PORT); //填充默认端口//

   
    int ret1 = bind(sockrecv, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR)); //绑定套接字//
    if (ret1 < 0) {
        closesocket(sockrecv);
        WSACleanup();
        perror("bind");
        printf("警告: 绑定失败!\n");
        return(FALSE);
    }

    printf("等待连接......");
    int ret2 = listen(sockrecv, 5); //开始监听,限制5个连接//
 if (ret2 < 0) {
  closesocket(sockrecv);
  WSACleanup();
  perror("listen");
  printf("警告: 监听失败!\n");
  return(FALSE);
 }

    SOCKADDR_IN addrCli;
    memset(&addrCli, '\0', sizeof(addrCli));
    int len = sizeof(SOCKADDR);
   
 SOCKET sockCli=accept(sockrecv, (SOCKADDR*)&addrCli, &len); //开始接收//
    if(sockCli < 0) {
        closesocket(sockrecv);
        WSACleanup();
        perror("accept");
        printf("警告: 接收失败!\n");
        return(FALSE);
 }

 printf("已经连接 %s\n", inet_ntoa(addrCli.sin_addr)); //显示连接端信息//

    int fileLength, cbBytesRet, cbLeftToRecv;
    BYTE* recvData = NULL;

    //创建文件//
    HANDLE hFile;
    hFile = CreateFile( filePath, //string 文件名或者绝对路径
                        GENERIC_WRITE, //long 读写权限,如果为零,表示只允许获取与一个设备有关的信息
                        FILE_SHARE_WRITE, //long 零表示不共享,FILE_SHARE_READ 或 FILE_SHARE_WRITE 表示允许对文件进行共享访问
                        NULL, //指向SECURITY_ATTRIBUTES结构的指针,判定返回的句柄是否可以被子进程继承,定义了文件的安全特性,用null表示不被继承。
                        OPEN_ALWAYS, //long 创建文件,如文件存在则会出错
                        0, //long 文件默认属性
                        NULL); //long 如果不为零,则指定一个文件句柄。新文件将从这个文件中复制扩展属性
    assert(hFile && "CreateFile!");
/*
 FILE* hFile;
 hFile = fopen(filePath, "wb");
*/

    printf("正在接收文件......\n");
 ///////////////////////////////////////////////////////////////////////////
    //首先接收文件长度信息//
    cbLeftToRecv = sizeof(fileLength);

    do {
        BYTE* bp = (BYTE*)(&fileLength) + sizeof(fileLength) - cbLeftToRecv;
        cbBytesRet = recv(sockCli, (char*)bp, cbLeftToRecv, 0); //流型数据的接收处理//

        if (cbBytesRet < 0 || cbBytesRet == 0 ) {
            perror("recv");
            printf("警告: 接收文件长度失败!\n");
            goto PreReturn;
  }
  
        cbLeftToRecv -= cbBytesRet;
 
 } while (cbLeftToRecv > 0);

    fileLength = ntohl(fileLength); //将文件的长度信息转化为本地字节序//

 ///////////////////////////////////////////////////////////////////////////
 //开始接收文件

    recvData = new BYTE[RECV_BUFFER_SIZE];
    cbLeftToRecv = fileLength;

 do {
  int iiGet, iiRecv;
       
        iiGet = (cbLeftToRecv < RECV_BUFFER_SIZE) ? cbLeftToRecv : RECV_BUFFER_SIZE;
        iiRecv = recv(sockCli, (char*)recvData, iiGet, 0); //流型数据的接收处理//

      //printf("cbLeftToRecv %d iiGet %d iiRecv %d sizeof(recvData) %d\n", cbLeftToRecv, iiGet, iiRecv, sizeof(recvData));
       
        if (iiRecv < 0 || iiRecv == 0) {
            perror("recv");
            printf("警告: 接收文件失败!\n");
            goto PreReturn;
  }

        DWORD dwLen;
        int ret3 = WriteFile(hFile, //Long,一个文件的句柄
                             recvData, //Any,要写入的一个数据缓冲区
                             iiRecv, //Long,要写入数据的字节数量。如写入零字节,表示什么都不写入,针对位于远程系统的命名管道,限制在65535个字节以内
                             &dwLen, //Long,实际写入文件的字节数量
                             NULL); //OVERLAPPED,倘若在指定FILE_FLAG_OVERLAPPED的前提下打开文件,这个参数就必须引用一个特殊的结构。
                                    //那个结构定义了一次异步写操作。否则,该参数应置为空(将声明变为ByVal As Long,并传递零值)
/*
        int ret3 = fwrite(recvData, RECV_BUFFER_SIZE, 1, hFile);
        if (ret3 == 0) printf("警告: 文件写入出错!\n");
*/
        cbLeftToRecv -= iiRecv;

 } while (cbLeftToRecv > 0);
 
    printf("发送完成.\n");

/*
    fclose(hFile);
    hFile = fopen(filePath, "rb");
    if (hFile !=NULL) { //取得文件大小//
        fseek(hFile, 0L, SEEK_END);
        fileLength = ftell(hFile);
        fseek(hFile, 0L, SEEK_SET);
    }
*/
    //fileLength = GetFileSize(hFile, NULL);
    //printf("test: 文件长度 %d\n", fileLength);
 
    //接收结束,释放内存,关闭连接//
    PreReturn :
    delete recvData;
    CloseHandle(hFile);
    closesocket(sockrecv);
    WSACleanup();

    return(0);
}

///////////////////////////////////////////////////////////////////////////////
//发送函数
int SendFile() {

    char filePath[CHARLENGTH];
    char DST_IP[CHARLENGTH];
    DWORD dst_ip;

    printf("请输入目的IP地址 :\n");
    memset(&DST_IP, '\0', sizeof(DST_IP));
    scanf("\n%s", DST_IP);
    printf("请输入待发送文件的绝对地址 :\n");
    scanf("\n%s", filePath);

    WSADATA wsaData;
    WSAStartup(WINSOCK_VERSION, &wsaData);

    dst_ip = inet_addr(DST_IP); //取得目的ip//

    //建立连接//
 ///////////////////////////////////////////////////////////////////////////
    SOCKET socksend = socket(AF_INET, SOCK_STREAM, 0); //创建套接字//
    if (socksend < 0) {
        closesocket(socksend);
        WSACleanup();
        perror("socket");
        printf("警告: 创建套接字失败!\n");
        return(FALSE);
 }

    SOCKADDR_IN addrSrv; //struct sockaddr_in//
    memset(&addrSrv, 0, sizeof(addrSrv)); //初始化addr//
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_addr.s_addr = dst_ip; //填充目的ip//
    addrSrv.sin_port = htons(PORT); //填充默认端口//

    int ret1 = connect(socksend, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR_IN)); //连接目的地址//
    if (ret1 < 0) {
        closesocket(socksend);
        WSACleanup();
        perror("connect");
        printf("警告: 连接失败!\n");
        return(FALSE);
 }
 
    int fileLength, cbLeftToSend;
    BYTE* sendData = NULL;

    HANDLE hFile;
    hFile = CreateFile(filePath, //打开要传送的文件//
                       GENERIC_READ,
                       FILE_SHARE_READ,
                       NULL,
                       OPEN_EXISTING,
                       0,
                       NULL);
    assert(hFile && "CreateFile failed!");
/*
 FILE* hFile;
 hFile = fopen(filePath, "rb"); //打开要传送的文件//

    if (hFile !=NULL) { //取得文件大小//
        fseek(hFile, 0L, SEEK_END);
        fileLength = ftell(hFile);
    }
*/
    fileLength = GetFileSize(hFile, NULL);
 
    printf("正在发送文件......\n");
    ///////////////////////////////////////////////////////////////////////////
    //首先传送文件长度给接收端//
    fileLength = htonl(fileLength); //转化为网络字序//
    cbLeftToSend = sizeof(fileLength);

  //printf("fileLength %d cbLeftToSend %d\n", fileLength, cbLeftToSend);

    do {
        int cbBytesSend;
        BYTE* bp = (BYTE*)(&fileLength) + sizeof(fileLength) - cbLeftToSend;
        cbBytesSend = send(socksend, (const char*)bp, cbLeftToSend, 0);

        if (cbBytesSend < 0) {
            perror("send");
            printf("警告: 传送文件长度错误!\n");
            goto PreReturn;
  }

        cbLeftToSend -= cbBytesSend;

 } while (cbLeftToSend > 0);

    ///////////////////////////////////////////////////////////////////////////
    //开始发送文件//

    sendData = new BYTE[SEND_BUFFER_SIZE];
    assert(sendData && "Allocate memory failed!");
    cbLeftToSend = GetFileSize(hFile, NULL);

    do { //循环发送//
        int sendThisTime, doneSoFar, buffOffset;
  
        DWORD dwLen;
        sendThisTime = ReadFile(hFile, sendData, SEND_BUFFER_SIZE, &dwLen, NULL);
        sendThisTime = dwLen;
/*
        memset(sendData, 0, sizeof(sendData));
        fread(sendData, SEND_BUFFER_SIZE, 1, hFile);
        sendThisTime = sizeof(sendData);
*/

        buffOffset = 0;

      //printf("cbLeftToSend %d字节 sendThisTime %d dwLen %d\n", cbLeftToSend, sendThisTime, dwLen);
  
        do {
            doneSoFar = send(socksend, (const char*)(sendData + buffOffset), sendThisTime, 0);

          //printf("1 cbLeftToSend %d sendThisTime %d buffOffset %d doneSoFar %d\n", cbLeftToSend, sendThisTime, buffOffset, doneSoFar);

            if (doneSoFar < 0) {
                perror("send");
                printf("警告: 文件发送错误!\n");
                goto PreReturn;
   }

            buffOffset += doneSoFar;
            sendThisTime -= doneSoFar;
            cbLeftToSend -= doneSoFar;

          //printf("2 cbLeftToSend %d sendThisTime %d buffOffset %d doneSoFar %d\n", cbLeftToSend, sendThisTime, buffOffset, doneSoFar);

  } while (sendThisTime > 0);
 
 } while (cbLeftToSend > 0);

    printf("发送完成.\n");

    //发送结束,释放内存,关闭连接//
    PreReturn :
    delete sendData;
    closesocket(socksend);
    WSACleanup();

    return(0);
}

int usage(char msg[]) {
    printf( " -----------------------------------------------------------\n"
            "|  准备好接收数据请输入    -r                               |\n"
            "|  准备好发送数据请输入    -s                               |\n"
            "|  获取帮助请输入          -h                               |\n"
            "|  退出本程序请输入        -q                               |\n"
            " -----------------------------------------------------------\n%s\n", msg);
    return(TRUE);
}


 




Re:WinSock实现网络文件传输程序
bricks发表评论于2007-4-1 20:02:00
有一个很严重的bug:接收文件,存在同名文件的时候并不提示用户,而是直接覆盖。



Re:WinSock实现网络文件传输程序
rocket323(游客)发表评论于2007-7-26 20:54:00
很好啊,解决了我几天的困惑,多谢了!



Re:WinSock实现网络文件传输程序
bricks发表评论于2007-7-27 21:06:00
谢谢捧场,我学这个的时候也是参考了好多前辈门的资料



处理 SSI 文件时出错

发表评论:

    大名:
    密码: (游客无须输入密码)
    主页:
    标题:
    教育人博客页面数据载入,请耐心等待


Powered by Oblog.