1. Этот сайт использует файлы cookie. Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie. Узнать больше.

Передача файлов через сокет

Тема в разделе "Программирование", создана пользователем fadetoblack, 15.06.07.

  1. fadetoblack

    fadetoblack Участник

    118
    0
    пере мной "встала" задача, да сиго нечего подобного не писал
    так как установленных средств разработки был только Builder6 псиал на нем.

    Вот условие:
    Необходимо организовать надежную передачу файлов между двумя узлами сети . Клиент соединяется с сервером по консольной команде connect [servemame ]: [port ]. После этого пользователь может запросить у сервера получение любого файла, находящегося в рабочем каталоге сервера с помощью команды get [filename ]. Сервер разбивает файл на датаграммы, и отправляет их клиенту. Клиент собирает файл из полученных датаграмм в своем рабочем каталоге. Затем, при получении всего файла, открывает его с помощью
    CreateProcess И команды "start filename".

    Для решения задачи с использованием протокола TCP также требуется разработать протокол обмена, но главной сложностью будет являться определение границ передаваемых сообщений, поскольку надежность и порядок доставки обеспечивает сам протокол. Кроме того, немаловажным будет обеспечить устойчивую работу сервера при отключении / ошибках клиентов. Сервер должен поддерживать одновременную работу с 254 клиентами.

    все что сумел это написать
    не смог, вернее не понимаю
    принцип заполнения буфера при чтении файла отправление его по сокету
    и получение и запись на стороне клиента


    Код прилагается:
    Сервер:
    --------------------------------------------------------------------------
    //---------------------------------------------------------------------------

    #include "stdio.h"
    #include <winsock2.h>
    #include <conio.h>
    #include <vcl.h>
    #pragma hdrstop
    #include "iostream.h"
    //---------------------------------------------------------------------------

    #pragma argsused

    // размер буфера приемника передачика
    const UINT BUF_SIZE = 256;
    // структура для передачи функции параметров потока
    struct SessionParam
    {
    SOCKET acceptSocket;
    int clientNum;
    };
    // потока облуживания клиента
    DWORD WINAPI SessionThread( LPVOID lpParam )
    {

    SessionParam sp = *(SessionParam*)lpParam;
    delete lpParam;

    printf( "Start session %d\n", sp.clientNum) ;

    int bytesSent, bytesRecv; // кол-во переданных принятых байт
    char sendbuf[BUF_SIZE]; // буфер передачи
    char recvbuf[BUF_SIZE]; // буфер приема
    char bufferRead[BUF_SIZE];
    // oeee recv-send
    while (1)
    {
    // принимаем даннные клиента
    bytesRecv = recv( sp.acceptSocket, recvbuf, 255, 0 );
    if (bytesRecv == SOCKET_ERROR) break;
    printf( "\tSession %d, bytes recived: %ld\n", sp.clientNum, bytesRecv ) ;
    if (bytesRecv == 0) break;
    //------------------------------------------------------------------------------
    int FileNam=0;
    //куча объявлений))))
    int nam,a,b;
    LPCTSTR lpFileName;
    LPCTSTR lpFileName1;
    AnsiString Str1;
    AnsiString Str2;
    AnsiString D="1.txt";
    //char D;
    AnsiString DriveStrings;
    DWORD dwBytes; //aooa?
    char buf[32];
    BOOL bResult,bResultWrite;
    DWORD dwBytes1;
    DWORD Folder;
    DWORD File;
    DWORD FolNam;

    HANDLE hFndF,hFileRecv,hFileRecv1; //oeacaoaeu
    WIN32_FIND_DATA FindFile;
    TCHAR lpBuffer[MAX_PATH];
    //scanf("%s\n",D.c_str());
    DWORD nBufferLength;
    GetCurrentDirectory(sizeof(lpBuffer),lpBuffer);
    printf("%s\n",lpBuffer);
    Str1=lpBuffer+String("\\RecvFile\\*.*");
    printf("%s\n",Str1);
    hFndF=FindFirstFile(Str1.c_str(), &FindFile);
    lpFileName=FindFile.cFileName;
    if (hFndF!=INVALID_HANDLE_VALUE){
    do{
    Folder=FindFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
    if (AnsiString(FindFile.cFileName)!=".")
    if (AnsiString(FindFile.cFileName)!=".."){
    {
    if (!Folder){

    if (strcmp(D.c_str(),FindFile.cFileName)==0){
    Str1=lpBuffer+String("\\RecvFile\\")+FindFile.cFileName;


    hFileRecv= CreateFile(

    Str1.c_str(), // pointer to name of the file
    GENERIC_READ, // access (read-write) mode
    FILE_SHARE_READ, // share mode
    NULL, // pointer to security attributes
    OPEN_EXISTING, // how to create
    FILE_ATTRIBUTE_NORMAL, // file attributes
    NULL // handle to file with attributes to copy
    );
    hFileRecv1= CreateFile( // OpenFile

    "1.txt", // pointer to name of the file
    GENERIC_WRITE, // access (read-write) mode
    NULL, // share mode
    NULL, // pointer to security attributes
    CREATE_ALWAYS, // how to create
    FILE_ATTRIBUTE_NORMAL, // file attributes
    NULL // handle to file with attributes to copy
    );

    do{
    bResult=ReadFile ( hFileRecv, // aane?eioi? ioe?uoiai oaeea
    &bufferRead, // oeacaoaeu ia aooa?, a eioi?ue

    16, // ?eoaai ii 1 aaeoo
    &dwBytes, // eie-ai ?aaeuii n?eoaiiuo aaeo
    NULL);
    send( sp.acceptSocket, bufferRead, strlen(bufferRead)+1, 0 );
    ВОТ ЗДЕСЬ начинаются траблы
    bResultWrite= WriteFile(hFileRecv1, // handle to file to write to
    &bufferRead, // pointer to data to write to file
    dwBytes, // number of bytes to write
    &dwBytes1, // pointer to number of bytes written
    NULL // pointer to structure needed for overlapped I/O
    );

    }
    while(dwBytes1>0);
    CloseHandle(hFileRecv1);


    DriveStrings=Str2.c_str();
    printf("%s\n",Str2);
    }
    FileNam=FileNam+1;
    printf("%s\n",&FindFile.cFileName);
    }
    }
    }
    }
    while (FindNextFile(hFndF,&FindFile)!=0);
    }
    printf("Tolal File: %d\n",FileNam);
    //------------------------------------------------------------------------------
    // CopyMemory(sendbuf, recvbuf, bytesRecv);

    // ionueaai ?acoeuoaoa ia?aoii eeeaioo
    bytesSent = send( sp.acceptSocket, sendbuf, bytesRecv, 0 );
    if (bytesSent == SOCKET_ERROR) break;
    printf("tSession %d, bytes send: %ld\n",sp.clientNum,bytesSent);


    }
    printf( "End session %d\n", sp.clientNum) ;
    return 0;
    }
    // noa?oiaay ooieoey aey iioiea -
    // oaaeii aey nicaaiey iiaiai iioiea SessionThread

    void SessionThreadStart( SOCKET acceptSocket, int clientNum )
    {
    SessionParam* sp = new SessionParam;
    sp->acceptSocket = acceptSocket;
    sp->clientNum = clientNum;
    // nicaaai iiaue iioie-nanne?
    HANDLE hThread = CreateThread( NULL, 0, SessionThread, (PVOID)sp, 0, NULL) ;
    CloseHandle(hThread) ; // e n?aco ?a cae?uaaai aai aane?eioi?
    }
    // aeaaiue iioie na?aa?a
    int _tmain(int argc, _TCHAR* argv[])
    {
    // Eieoeaeecaoey nieaoia
    WSADATA wsaData;
    int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
    if ( iResult != NO_ERROR )
    {
    printf("Error at WSAStartup()\n");
    _getch();
    return -1;
    }
    // Nicaaiea iiaiai ON?-nieaoa
    SOCKET m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
    if ( m_socket == INVALID_SOCKET ) {
    printf( "Error at socket!): %ld\n", WSAGetLastError());
    WSACleanup() ;
    _getch();
    return -1;
    }
    /*
    BOOL so_reuse = TRUE;
    setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&so_reuse, sizeof(BOOL)
    */
    // I?eaycea (binding) nieaoa e aa?ano e ii?oo
    sockaddr_in service;
    service.sin_family = AF_INET;
    service.sin_addr.s_addr = inet_addr( "127.0.0.1" );
    service.sin_port = htons( 27015 );
    if ( bind( m_socket, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR)
    {
    printf( "bind() failed: %ld\n", WSAGetLastError());
    closesocket(m_socket) ;
    WSACleanup();
    _getch();
    return -1;
    }
    // ia?aaiaei nieao a "neooa?uee" ?a?ei
    if ( listen( m_socket, SOMAXCONN ) == SOCKET_ERROR )
    {
    printf( "Error listen() on socket.\n");
    closesocket(m_socket );
    WSACleanup();
    _getch();
    return -1;
    }
    int clientNum = 0;

    // aaneiia?iue oeee ianeo?eaaiey eeeaioia
    while (1) {
    printf( "Waiting for next client to connect...\n" );
    // "eiiey" nieaoa m_socket - nicaaaony ooieoeae accept
    SOCKET acceptSocket = SOCKET_ERROR;
    // i?eieiaai connect'u eeeaioia ...
    while (acceptSocket == SOCKET_ERROR) {
    // ... nicaaaay eiiee enoiaiiai nieaoa
    acceptSocket = accept( m_socket, NULL, NULL );
    }
    printf( "Client %d is connected\n", ++clientNum) ;
    // nicaaai iiaue iioie, ?aaioa?uee n eeeaioii
    SessionThreadStart( acceptSocket, clientNum ) ;
    }
    // caaa?oaiea ?aaiou na?aa?a
    closesocket(m_socket);
    WSACleanup() ;
    // ?aai aaiaa iieuciaaoaey
    _getch();
    return 0;
    }
    //------------------------------------------------------------------------
     
  2. fadetoblack

    fadetoblack Участник

    118
    0
    код клиента:
    int main(int argc, char* argv[])
    {
    // return 0;
    //}
    // eia i?ia?aiiu-eeeaioa
    //int _tmain(int argc, _TCHAR* argv[])
    //{
    // Eieoeaeecaoey nieaoia
    WSADATA wsaData;
    int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
    if ( iResult != NO_ERROR )
    printf("Error at WSAStartup()\n");

    // Nicaaiea nieaoa

    SOCKET m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP );

    if ( m_socket == INVALID_SOCKET ) {
    printf( "Error at socket!): %ld\n", WSAGetLastError());
    WSACleanup() ;
    return -1;
    }
    /*
    BOOL so_reuse = TRUE;
    setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&so_reuse, sizeof(BOOL))
    */
    // Nicaaiea niaaeiaiey n na?aa?ii "127.0.0.1"
    /* char ip_address[10];
    char a[10];
    printf("Connect [ip_address]: ");
    gets(ip_address);
    printf("\n");
    printf(" [port]: ");
    DWORD port;
    scanf("%d",&port);

    printf("\n"); */
    sockaddr_in clientService;
    clientService.sin_family = AF_INET;
    clientService.sin_addr.s_addr = inet_addr("127.0.0.1");
    clientService.sin_port = htons( 27015 );
    if ( connect(m_socket, (SOCKADDR*)&clientService, sizeof(clientService) ) == SOCKET_ERROR) {
    printf( "Failed to connect.\n" );
    closesocket(m_socket);
    WSACleanup() ;
    return -1;
    }
    // aaneiia?iue oeee ia?aaa?e/i?eaia aaiiuo
    while (1)
    {
    // Send and receive data.
    int bytesSent; // ?enei iineaiiuo aaeo
    int bytesRecv = SOCKET_ERROR; // ?enei i?eiyouo aaeo
    char sendbuf[BUF_SIZE]; // aooa? ia?aaa?e
    char recvbuf[BUF_SIZE]; // aooa? i?eaia
    // iieo?aai no?ieo io iieuciaaoaey
    printf("Please enter some text: ");
    gets(sendbuf);

    if (lstrcmpi(sendbuf, "quit") == 0) break;
    // ia?aaaai no?ieo na?aa?o
    bytesSent = send(m_socket, sendbuf, strlen(sendbuf)+1, 0 );
    printf( "Bytes Sent: %ld\n", bytesSent );
    // oeee i?eaia aaiiuo
    while(bytesRecv==SOCKET_ERROR){
    bytesRecv=recv(m_socket,recvbuf,32,0);
    if ( bytesRecv == 0 || bytesRecv == WSAECONNRESET ) {
    printf( "Connection Closed.\n");
    break;
    }
    if (bytesRecv < 0)
    return -1;
    printf( "Bytes Recv: %ld\n", bytesRecv );
    }








    printf( "Server say: %s\n", recvbuf );

    }
    // caaa?oaiea ?aaiou eeeaioa
    int err = closesocket( m_socket );
    if ( err == SOCKET_ERROR ) {
    printf ("Error closing socket!");
    WSACleanup() ;
    _getch();
    }
    return 0;
    }

    добавлено через 7 минут
    бытесРецв=рецв(м_соцкет,рецвбуф,32,0);
    бытесСент = сенд(м_соцкет, сендбуф, стрлен(сендбуф)+1, 0 );


    вопросы
    1)как работает передача\ прием
    2)как как реализовать контроль целосности передоваемого файла
    3)...еще там в коде сервера при чтении из файла, нужно условие "конца файла"

    Р.С. в клиенте нет кода на создание файла и запись в него, он лежит в сервере там где и чтение:)

    добавлено через 9 минут
    bytesSent = send(m_socket, sendbuf, strlen(sendbuf)+1, 0 );
    bytesRecv=recv(m_socket,recvbuf,32,0);

    чертов транслит:frustrate
     
  3. Bob

    Bob Активный

    21.804
    0
    А готовый ФТП поюзать религия не велит? Или через ХТТП?
     
  4. HorstWessel

    HorstWessel Активный участник

    1.585
    0
    Используй фтп. В каждой операционке есть клиент.

    По программированию: Обычно функции считывающие из сокета (или любого другого потока) возвращают число реально скачаных байт или -1 если больше ничего нет. TCP сам заботиться о гарантии (и порядке) доставки пакетов. В крайнем случае можно писать сначала в поток длинну файла, а затем сам файл. На клиенте в том же порядке читается сначала длина и потом файл (с уже известной длиной).
     
  5. резет

    резет Участник

    119
    0
    есть код правда на дельфи по пересылке файлов.Могу кинуть
    Я сначала там создавал и отправлял управляющуюю посылку, а потом взависимости оот нее либо передал клиенту файл,либо забирал
     
  6. fadetoblack

    fadetoblack Участник

    118
    0
    BOOL TransmitFile(
    SOCKET hSocket,
    HANDLE hFile,
    DWORD nNumberOfBytesToWrite,
    DWORD nNumberOfBytesPerSend,
    LPOVERLAPPED lpOverlapped,
    LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,
    DWORD dwFlags
    );

    вот нашел функцию интереснуютеперь не могу корекно ей воспользоваться....
    как на сторане клиента, узнать что файл передан?
    нет, мне надо на С++ самому написать...религия не велит(