c++socketを適用してC/Sエンドファイルの転送を実現

26887 ワード

人は生から死までの生活の生活の一歩一歩がカウンターを隔てた現金の商売関係であるべきで、もし私たちがこのように天国に登らなければ、天国も経済学のために手配された場所ではなく、そこには私たちのことはありません.起首是办公器端,大概说下贱程:办公器作成スレッド向理惩罚応答accept()は、クライアント接続要求を引き継ぐと、送信する指定されたファイルデータの総サイズをクライアントに取得し、次に、送信するファイルの数をクライアントに転送してファイルデータを送信し、毎回輪廻が読み取ったデータの実際のサイズを断定する.実際に読み込まれたデータの合計サイズが0の場合、デフォルトファイル送信は停止します.次に、プロセッササーバ側の実装を示します.
心は生活しているところではありませんが、爱しているところです.プロジェクトグループの宣言:
public:
    afx_msg void OnBnClickedButton1();
public:
    BOOL InitSocket();    //         

    static DWORD WINAPI ThreadProc(LPVOID lpParameter);    //          accept()

実装プロジェクトグループ:
void CSendFileServerDlg::OnBnClickedButton1()
{
    // TODO:                 
    if (InitSocket())
    {
        GetDlgItem(IDC_EDIT1)->SetWindowText(_T("     。。。 
"));

        //    
        HANDLE hThread = CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
        //
        CloseHandle(hThread);
    }
}

BOOL CSendFileServerDlg::InitSocket()
{
    //      
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;
    wVersionRequested = MAKEWORD( 11 );
    err = WSAStartup( wVersionRequested, &wsaData );
    if ( err != 0 ) 
    {
        return FALSE;
    }

    if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) 
    {
            WSACleanup( );
            return FALSE;
    }

    //     
    //SOCKET m_socket=socket(AF_INET,SOCK_STREAM,0);
    m_socket=socket(AF_INET,SOCK_STREAM,0);
    if (m_socket == INVALID_SOCKET)
    {
        AfxMessageBox(_T(""));
        return FALSE;
    }

    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
    addrSrv.sin_family=AF_INET;
    addrSrv.sin_port=htons(8099);

    err = bind(m_socket,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));    //      
    if (err==SOCKET_ERROR)
    {
        closesocket(m_socket);
        AfxMessageBox(_T(""));
        return FALSE;
    }
    listen(m_socket,5);//  

    return TRUE;

}

DWORD WINAPI CSendFileServerDlg::ThreadProc(LPVOID lpParameter)
{
    SOCKADDR_IN addrClient;
    int len = sizeof(SOCKADDR);

    whiletrue)
    {
        SOCKET sockConn=accept(m_socket,(SOCKADDR*)&addrClient,&len);

        CString filename = _T("E:\test.zip");
        HANDLE hFile;
        unsigned long long file_size = 0;

        char Buffer[1024];
        DWORD dwNumberOfBytesRead;

        hFile = CreateFile(filename,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
        file_size = GetFileSize(hFile,NULL);
        send(sockConn,(char*)&file_size,sizeof(unsigned long long)+1,NULL);

        do 
        {
            ::ReadFile(hFile,Buffer,sizeof(Buffer),&dwNumberOfBytesRead,NULL);
            ::send(sockConn,Buffer,dwNumberOfBytesRead,0);
        } while (dwNumberOfBytesRead);


        CloseHandle(hFile);
    }

    return 0;
}

コードに記載されているように、各送信単位はunsigned char[1024]サイズ(法度はcharがunsigned charであるべきである[1024])であるため、バイトシーケンスの問題を収集しても、エンド・エンド・エンド・エンド・ツーエンドを推敲する必要はない.
サーバー側は一時的にマルチクライアントの同時接続をサポートしておらず、その後に追加される可能性があります.の
-------------------------------------------
以下はクライアントであり、同様にクライアントプロセスも大まかに言えば、クライアントは手動でIpアドレスとエンドスローガンを記入する機能を増加させる(エンドスローガンは暫定的に8099).および転送ファイルデータの進捗バーの表示、および以下の簡単な状況表示.客観端は記入したIPアドレスで接続事務器が操作し,クライアント接続事務器が成功すれば直接に事務器側から送信される送信するファイルデータの総サイズを取得し,取得ファイルの総サイズ>0であれば指定した経路に輪廻してデータを書く.ここで輪廻書きファイル停止フラグは、実際に書くたびに累積値がサーバ側から取得したファイルの総サイズであれば、ファイルデータが成功したことを黙示し、輪廻を停止します.大体このような過程です.コード実装:
クライアント宣言プロジェクトグループ:
public:
	afx_msg void OnBnClickedButton1();

	BOOL InitSocket();
	void ConnectServer();
	void ConnectRecvFileData(DWORD ip,int port);

private:
	CProgressCtrl *m_progress; //   

進捗バーはOnInitDialog()で初期化されます.
BOOL CRecvFileClientDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    //  “  ...”           。

    // IDM_ABOUTBOX           。
    ASSERT((IDM_ABOUTBOX & 0 xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0 xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        CString strAboutMenu;
        strAboutMenu.LoadString(IDS_ABOUTBOX);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }

    //          。              ,     
    //       
    SetIcon(m_hIcon, TRUE);            //      
    SetIcon(m_hIcon, FALSE);        //      

    // TODO:             

    m_progress = (CProgressCtrl*)GetDlgItem(IDC_PROGRESS1); 
    m_progress->SetPos(0); 

    return TRUE;  //           ,     TRUE
}

クライアント実装プロジェクトグループ:
void CRecvFileClientDlg::OnBnClickedButton1()
{
    // TODO:                 
    ConnectServer();
    
}


BOOL CRecvFileClientDlg::InitSocket()
{
    //      
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;
    wVersionRequested = MAKEWORD( 11 );
    err = WSAStartup( wVersionRequested, &wsaData );
    if ( err != 0 ) 
    {
        return FALSE;
    }

    if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) 
    {
        WSACleanup( );
        return FALSE;
    }

    return TRUE;

}

void CRecvFileClientDlg::ConnectRecvFileData(DWORD ip,int port)
{
    
    unsigned long long file_size=0;
    SOCKET sockClient = socket(AF_INET,SOCK_STREAM,0);
    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr=htonl(ip);
    addrSrv.sin_port=ntohs(port);
    addrSrv.sin_family = AF_INET;
    //connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
    //recv(sockClient,(char*)&file_size,sizeof(unsigned long long)+1,NULL);

    if (!connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)))
    {
        GetDlgItem(IDC_SHOWINFO)->SetWindowText(_T(""));
        GetDlgItem(IDC_SHOWINFO)->SetWindowText(_T(""));

        

        recv(sockClient,(char*)&file_size,sizeof(unsigned long long)+1,NULL);

        unsigned short maxvalue = file_size;    //                    
        m_progress->SetRange(0,maxvalue); 

        if (file_size>0)
        { 
            GetDlgItem(IDC_SHOWINFO)->SetWindowText(_T(""));
            GetDlgItem(IDC_SHOWINFO)->SetWindowText(_T("      d:\test.zip 
"));

            DWORD dwNumberOfBytesRecv=0;
            DWORD dwCountOfBytesRecv=0;
            char Buffer[1024];
            CString filename = _T("d:\test.zip");
            HANDLE hFile;
            hFile = CreateFile(filename,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);

            do 
            {
                m_progress->SetPos(dwCountOfBytesRecv);//     

                dwNumberOfBytesRecv = ::recv(sockClient,Buffer,sizeof(Buffer),0);
                ::WriteFile(hFile,Buffer,dwNumberOfBytesRecv,&dwNumberOfBytesRecv,NULL);
                dwCountOfBytesRecv += dwNumberOfBytesRecv;                
            } while (file_size - dwCountOfBytesRecv);


            CloseHandle(hFile);
            
            GetDlgItem(IDC_SHOWINFO)->SetWindowText(_T(""));
            GetDlgItem(IDC_SHOWINFO)->SetWindowText(_T(""));
            AfxMessageBox(_T("      !"));//      
        }else
        {
            AfxMessageBox(_T(""));
        }
    }else
    {
        AfxMessageBox(_T("       、   IP      !"));
    }
    
    

    closesocket(sockClient);//     


}

void CRecvFileClientDlg::ConnectServer()
{
    if (InitSocket())
    {
        DWORD strIp =NULL;
        CString strPort = _T("");

        ((CIPAddressCtrl*)GetDlgItem(IDC_IP))->GetAddress(strIp);
        GetDlgItem(IDC_PORT)->GetWindowText(strPort);

        if (strIp==NULL||strPort=="")
        {
            AfxMessageBox(_T("Ip   Port         !"));

        }else
        {
            int port = atoi(strPort.GetBuffer(1));
            ConnectRecvFileData(strIp,port);
            
        }
        
    }
    

}

结末:比来はsocketを使ってプログラミングの器材を収集して、だから根蒂基础のC/S端のデータの収集の伝达を书いてみて、どれらの不足の地方があって、见る进歩の先辈达は惜しまないで教えてください!!!