Winsock Передача Целого Файла По Tcp Протоколу

Тема в разделе "Общие вопросы по С и С++", создана пользователем alekssgor, 29 окт 2011.

  1. alekssgor

    alekssgor Well-Known Member

    Регистрация:
    26 май 2008
    Сообщения:
    118
    Симпатии:
    0
    Как с помощью функции WinSock TransmiteFile передать файл???
    Создал функции сервера и клиента. Передаю строку всё работает. Как передать целый файл???
    Код (Text):
    #include <winsock2.h>
    #include <mmsystem.h>

    //Функции для создания сервера
    DWORD WINAPI ClientThread(LPVOID lpParam)
    {
    SOCKET sock = (SOCKET)lpParam;
    char szRecvBuff[1024], szSendBuff[1024];
    int ret;
    //Запуск бесконечного цикла
    while(1)
    {
    //Получение данных
    ret = recv(sock, szRecvBuff, 1024, 0);
    //Проверка полученных данных
    if(ret == 0) break;
    else if(ret == SOCKET_ERROR)
    {
    MessageBoxA(0, "Ошибка при получении данных", "Сообщение", 0);
    break;
    }
    szRecvBuff[ret] = '\0';
    //Здесь можно поставить проверку принятого текста
    //в переменной szRecvBuff
    if(strstr(szRecvBuff, "get"))
    {
    //Открываем шуточным троянчиком CDRom
    MCI_OPEN_PARMS OpenParm;
    MCI_SET_PARMS SetParm;
    MCIDEVICEID dID;
    OpenParm.lpstrDeviceType = "CDAudio";
    mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE, (DWORD_PTR)&OpenParm);
    dID = OpenParm.wDeviceID;
    mciSendCommand(dID, MCI_SET, MCI_SET_DOOR_OPEN, (DWORD_PTR)&SetParm);
    Sleep(5000);
    mciSendCommand(dID, MCI_SET, MCI_SET_DOOR_CLOSED, (DWORD_PTR)&SetParm);
    mciSendCommand(dID, MCI_CLOSE, MCI_NOTIFY, (DWORD_PTR)&SetParm);

    }
    //else if(ищем файлы .doc и забираем. Нет не будем!!!!!)
    //Подготовка строки для отправки
    strcpy(szSendBuff, "Command get OK");
    //Отправка содержимого переменной szSendBuff клиенту
    ret = send(sock, szSendBuff, sizeof(szSendBuff), 0);
    if(ret == SOCKET_ERROR) break;
    }
    return 0;
    }

    DWORD WINAPI NetThread(LPVOID lpParam)
    {
    SOCKET sServerListen, sClient;
    struct sockaddr_in localaddr, clientaddr;
    HANDLE hThread;
    DWORD dwThreadId;
    int iSize;

    //Создание сокета
    sServerListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
    if(sServerListen == SOCKET_ERROR)
    {
    MessageBoxA(0, "ошибка при создании socketa", "Ошибка", 0);
    return 0;
    }
    //Заполнение структуры localaddr типа sockaddr_in
    //содержащей информацию о локальном адресе сервера и номером порта
    localaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    localaddr.sin_family = AF_INET;
    localaddr.sin_port = htons(5050);

    //Связывание адреса с переменной localaddr типа sockaddr_in
    if(bind(sServerListen, (struct sockaddr *)&localaddr, sizeof(localaddr)) == SOCKET_ERROR)
    {
    MessageBoxA(0, "Ошибка при выполнении функции bind", "Ошибка", 0);
    return 0;
    }
    //Вывод об удачной операции bind
    MessageBoxA(0, "Bind OK", "Сообщение", 0);
    //Запуск прослушивания порта
    listen(sServerListen, 4);
    //Вывод сообщения об удачном начале операции прослушивания
    MessageBoxA(0, "Listen OK", "Сообщение", 0);
    //Запуск бесконечного цикла
    while(1)
    {
    iSize = sizeof(clientaddr);
    //Приём соединений из очереди. Если его нет,
    //то функция будет ожидать соединение с клиентом
    sClient = accept(sServerListen, (struct sockaddr *)&clientaddr, &iSize);
    //Проверка корректности идентификатора клиенского сокета
    if(sClient == INVALID_SOCKET)
    {
    MessageBoxA(0, "Ошибка при выполнении функции accept", "Ошибка", 0);
    break;
    }
    MessageBoxA(0, inet_ntoa(clientaddr.sin_addr), "Подключение к серверу", 0);
    //Если подключаемся не мы а чел просканировавший порты то выходим из цикла
    if(!strstr( inet_ntoa(clientaddr.sin_addr), "127.0.0.1")) break;
    //Создание нового потока для работы с клиентом
    hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)sClient, 0, &dwThreadId);
    if(hThread == NULL)
    {
    MessageBoxA(0, "Ошибка при создании потока", "Ошибка", 0);
    break;
    }
    CloseHandle(hThread);
    }
    //Закрытие сокета после работы с потоком
    closesocket(sServerListen);
    return 0;
    }
    //Функция для создания клиента
    DWORD WINAPI NetThread(LPVOID lpParam)
    {
    SOCKET sClient;
    char szBuffer[1024];
    int ret, i;
    struct sockaddr_in server;
    struct hostent *host = NULL;
    char szServerName[1024], szMessage[1024];

    strcpy(szMessage, "get");
    strcpy(szServerName, "127.0.0.1");
    //Создание сокета
    sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(sClient == INVALID_SOCKET)
    {
    MessageBoxA(0, "Ошибка при создании сокета", "Ошибка", 0);
    return 1;
    }
    //Заполнение структуры с адресом сервера и номером порта
    server.sin_family = AF_INET;
    server.sin_port = htons(5050);
    server.sin_addr.s_addr = inet_addr(szServerName);
    //Если указано имя, то перевод символьного адреса сервера в IP
    if(server.sin_addr.s_addr == INADDR_NONE)
    {
    host = gethostbyname(szServerName);
    if(host == NULL)
    {
    MessageBoxA(0, "Ошибка при определении IP адреса", "Ошибка", 0);
    return 1;
    }
    strcpy((char*)&server.sin_addr, host->h_addr_list[0]);
    }
    //Соединение с сервером
    if(connect(sClient, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
    {
    MessageBoxA(0, "Ошибка при соединении с сервером", "Ошибка", 0);
    return 1;
    }
    //Отправка и приём данных
    ret = send(sClient, szMessage, strlen(szMessage), 0);
    if(ret == SOCKET_ERROR)
    MessageBoxA(0, "Ошибка при выполнении функции send", "Ошибка", 0);
    //Задержка
    Sleep(1000);
    //Получение данных
    char szRecvBuff[1024];
    ret = recv(sClient, szRecvBuff, 1024, 0);
    if(ret == SOCKET_ERROR)
    MessageBoxA(0, "Ошибка ппри получении данных", "Ошибка", 0);
    MessageBoxA(0, szRecvBuff, "Отправлены данные", 0);
    closesocket(sClient);
    }
     
  2. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    А что это такая за функция TransmiteFile, и где ты ее используешь?

    Так же как и строку не получается?
     
  3. alekssgor

    alekssgor Well-Known Member

    Регистрация:
    26 май 2008
    Сообщения:
    118
    Симпатии:
    0
    Опечатка TransmitFile
    Функция появилась в winsock2.h
    Если все функции без префекса WSA существуют не только в Windows но и в UNIX-системах то функция
    TransmitFile является расширением Microsoft и работает только в Windows(В справке говорится что не надо заботится о
    последовательном чтении и проверять количество отправленных данных потому что это гарантируется
    библиотекой WinSock2
    Выглядит следующим образом

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

    hSocket - сокет через который надо отправить данные

    hFile - указатель на открытый файл данные которого надо отправить

    nNumberOfBytesToWrite - количество отправляемых из файла байт.
    если 0 отправляется весь файл

    nNumberOfBytesPerSend - размер пакета для отправки если 0 то по умолчанию

    lpOverlapped - используется при перекрёстном вводе/выводе

    lpTransmitBuffers - содержит служебную информацию которую нужно послать до
    и после отправки файла. По этим данным на принимающей стороне
    можно определить начало и окончание передачи

    dwFlags - флаги
    TF_DISCONNECT - закрыть сокет после передачи данных
    TF_REUSE_SOCKET - подготовить сокет для повторного использования
    TF_WRITE_BEHIND - завершить работу не дожидаясь подтверждения
    о получении данных со стороны клиента


    typedef struct _TRANSMIT_FILE_BUFFERS{
    PVOID Head; //указатель на буфер содержащий содержащий данные
    которые надо отправить клиенту до начало отправки файла
    DWORD HeaderLength; // размер буфера Head
    PVOID Tail; //указатель на буфер содержащий данные
    которые надо отправить клиенту после завершения отправки файла
    DWORD TailLength; // размер буфера Tail
    }; TRANSMIT_FILE_BUFFERS;
     
  4. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Это все понятно. Но зачем ты привел этот код? Покажи тот код, в котором у тебя не получается при помощи TransmitFile передать файл по сети, и укажи что и где работает не так.
     
  5. alekssgor

    alekssgor Well-Known Member

    Регистрация:
    26 май 2008
    Сообщения:
    118
    Симпатии:
    0
    Как отослать не текстовый файл!!!!!
     
  6. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Так же как и текстовый!!!!!
     
Загрузка...
Похожие Темы - Winsock Передача Целого
  1. alekssgor
    Ответов:
    3
    Просмотров:
    3.269
  2. sergg
    Ответов:
    2
    Просмотров:
    5.231
  3. Corexis
    Ответов:
    0
    Просмотров:
    67
  4. Shouldercannon
    Ответов:
    0
    Просмотров:
    486
  5. Shouldercannon
    Ответов:
    0
    Просмотров:
    386

Поделиться этой страницей