一个简单的在本地传输文件的网络程序

来源:岁月联盟 编辑:猪蛋儿 时间:2012-11-17

经常在CSDN贴吧看见很多关于网络之间传输的例子(比如传输截屏文件),所以很想写一个作为学习。

此程序设定很简单,就是在本地传输。当然,要扩展到网络也很简单,改个ip就ok了。

基本思路:

双方遵循一个包头格式,根据包头确定之后的操作。

服务器代码:

[cpp] 
#include <string> 
#include <io.h> 
 
#define PORT 6666 
 
struct PacketHeader 

    char code[10];      // 指令:"EOF"=断开连接  "PIC"=接收图片 
    char name[50];      // 名字:包括后缀 
    LONG32 size;        // 大小:字节 
    PacketHeader() 
    { 
        memset(code,0,sizeof(code)); 
        memset(name,0,sizeof(name)); 
        size = 0; 
    } 
}; 
 
// 在本地传输图片 
void server() 

    WSADATA wd; 
    int ret = WSAStartup(MAKEWORD(2,2),&wd); 
    if(ret != 0) 
    { 
        cout<<"Initialize Winsock Failed! "<<GetLastError()<<endl;; 
        return; 
    } 
    cout<<"WSAStartup OK"<<endl; 
 
    sockaddr_in addr_serv,addr_cli; 
    int sock_listen,sock_accept; 
    try{ 
        sock_listen = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
        if(sock_listen == SOCKET_ERROR) 
        { 
            cout<<"create socket failed! "<<GetLastError()<<endl; 
            throw 1; 
        } 
        cout<<"socket OK"<<endl; 
 
        memset((void*)&addr_serv,0,sizeof(sockaddr)); 
        addr_serv.sin_family = AF_INET; 
        addr_serv.sin_addr.S_un.S_addr = INADDR_ANY; 
        addr_serv.sin_port = htons(PORT); 
 
        ret = bind(sock_listen,(sockaddr*)&addr_serv,sizeof(addr_serv)); 
        if(ret != 0) 
        { 
            cout<<"bind failed! "<<GetLastError()<<endl; 
            throw 2; 
        } 
        cout<<"bind OK"<<endl; 
 
        ret = listen(sock_listen,1); 
        if(ret != 0) 
        { 
            cout<<"listen failed! "<<GetLastError()<<endl; 
            throw 2; 
        } 
        cout<<"listen OK"<<endl; 
 
        int addrlen = sizeof(addr_cli); 
        sock_accept = accept(sock_listen,(sockaddr*)&addr_cli,&addrlen); 
        if(sock_accept == INVALID_SOCKET) 
        { 
            cout<<"accept failed! "<<GetLastError()<<endl; 
            throw 2; 
        } 
        cout<<"accept OK"<<endl; 
        closesocket(sock_listen);   //停止监听 
 
        while(true) 
        { 
            cout<<"输入:(EOF表示断开连接,文件名表示发送文件,例如sumos.txt)"<<endl; 
            string input; 
            cin>>input; 
            if(input.compare("EOF") == 0) 
            { 
                PacketHeader ph; 
                strcpy_s(ph.code,"EOF"); 
                send(sock_accept,(const char*)&ph,sizeof(ph),0); 
                break; 
            } 
            else  
            { 
                FILE* fp = NULL; 
                fopen_s(&fp,input.c_str(),"rb"); 
                if(fp == NULL) 
                { 
                    cout<<"打开失败"<<endl; 
                    continue; 
                } 
                else 
                { 
                    LONG32 sz = _filelength(_fileno(fp)); 
                    cout<<"文件打开成功,大小:"<<sz<<" Bytes"<<endl; 
                    PacketHeader ph; 
                    strcpy_s(ph.code,"PIC"); 
                    strcpy_s(ph.name,input.c_str()); 
                    ph.size = sz; 
                    send(sock_accept,(const char*)&ph,sizeof(ph),0); 
                    cout<<"已发送头部信息"<<endl; 
 
                    int nSend = 0; 
                    char buffer[1024]; 
                    while(nSend < sz) 
                    { 
                        int nBytes = fread(buffer,sizeof(char),1024,fp); 
                        if(nBytes <= 0)                           
                            break;                   
                        send(sock_accept,buffer,nBytes,0); 
                        cout<<"已发送 "<<nBytes<<" Bytes"<<endl; 
                        nSend += nBytes; 
                    } 
                    cout<<"总计发送 "<<nSend<<" Bytes"<<endl; 
                    fclose(fp); 
                } 
            } 
        } 
        closesocket(sock_accept); 
    }catch(int which){ 
        if(which == 2) 
            closesocket(sock_listen); 
        if(which == 3) 
            closesocket(sock_accept); 
    } 
    WSACleanup(); 

客户端代码:

[cpp]
#include <WinSock.h> 
#pragma comment(lib,"ws2_32.lib") 
 
#define IP      "127.0.0.1" 
#define PORT    6666 
 
struct PacketHeader 

    char code[10];      // 指令:"EOF"=断开连接  "PIC"=接收图片 
    char name[50];      // 名字:包括后缀 
    LONG32 size;        // 大小:字节 
    PacketHeader() 
    { 
        memset(code,0,sizeof(code)); 
        memset(name,0,sizeof(name)); 
        size = 0; 
    } 
}; 
 
void client()  

    WSADATA wd; 
    int ret = WSAStartup(MAKEWORD(2,2),&wd); 
    if(ret != 0) 
    { 
        cout<<"Initialize Winsock Failed! "<<GetLastError()<<endl;; 
        return; 
    } 
    cout<<"WSAStartup OK"<<endl; 
 
    sockaddr_in addr_serv; 
    int sock; 
    try{ 
        sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
        if(sock == SOCKET_ERROR) 
        { 
            cout<<"create socket failed! "<<GetLastError()<<endl; 
            throw 1; 
        } 
        cout<<"socket OK"<<endl; 
 
        memset((void*)&addr_serv,0,sizeof(sockaddr)); 
        addr_serv.sin_family = AF_INET; 
        addr_serv.sin_addr.S_un.S_addr = inet_addr(IP); 
        addr_serv.sin_port = htons(PORT); 
 
        ret = connect(sock,(sockaddr*)&addr_serv,sizeof(addr_serv)); 
        if(ret == SOCKET_ERROR) 
        { 
            cout<<"connect failed! "<<GetLastError()<<endl; 
            throw 2; 
        } 
        cout<<"connect OK"<<endl; 
 
        char buffer[1024]; 
        while(true) 
        { 
            int nRecv = recv(sock,buffer,1024,0); 
            if(nRecv <= 0) 
                continue; 
            else if(nRecv == sizeof(PacketHeader)) 
            { 
                PacketHeader ph; 
                memcpy_s(&ph,sizeof(ph),buffer,nRecv); 
                if(strcmp(ph.code,"EOF") == 0) 
                    break; 
                else if(strcmp(ph.code,"PIC") == 0) 
                { 
                    cout<<"文件名:"<<ph.name<<",大小:"<<ph.size<<endl; 
                    FILE* fp = NULL; 
                    fopen_s(&fp,ph.name,"wb"); 
                    if(fp == NULL) 
                    { 
                        cout<<"创建文件失败"<<endl; 
                        break; 
                    } 
                    else 
                    { 
                        nRecv = 0; 
                        while(nRecv < ph.size) 
                        { 
                            int nBytes = recv(sock,buffer,1024,0); 
                            if(nBytes <= 0) 
                                break; 
                            cout<<"已接收 "<<nBytes<<" Bytes"<<endl; 
                            fwrite(buffer,sizeof(char),nBytes,fp); 
                            nRecv += nBytes; 
                        } 
                        cout<<"共接收 "<<nRecv<<" Bytes"<<endl; 
                        fclose(fp); 
                    } 
                } 
                else 
                { 
                    cout<<"头部信息错误"<<endl; 
                    break; 
                } 
            } 
            else 
            { 
                buffer[nRecv] = '/0'; 
                cout<<buffer<<endl; 
            } 
        } 
        closesocket(sock); 
    }catch(int which){   
        if(which == 2) 
        closesocket(sock); 
    } 
    WSACleanup(); 

运行截图: