Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: C++ ошибка: "Сделана попытка выполнить операцию на объекте, не являющемся сокето  (Прочитано 9415 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Anbore
Новенький

ru
Offline Offline

« : 24-11-2016 01:55 » 

Всем доброго времени суток.
Имеется сервер и клиент. Нужно с клиента переслать бинарный файл на сервер и исполнить его.
Файл открывается в бинарном режиме, читает в буфер, делает send. Сервер делает recv и из буфера записывает в файл, потом переименовывает.
Пытаюсь переслать и получаю ошибку: "Сделана попытка выполнить операцию на объекте, не являющемся сокетом."

сервер
Код: (C++)
#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>
#include <locale.h>
#include <string>

#pragma comment(lib, "Ws2_32.lib")

#define PORT 6091

void getError(DWORD errCode)
   {
   char* error;
   FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
      NULL,
      errCode != 0 ? errCode : WSAGetLastError(),
      MAKELANGID(LANG_RUSSIAN, SUBLANG_DEFAULT),
      error,
      sizeof(error),
      NULL);  
   printf("\nОшибка: %s\n", error);
   getchar();
   }

int main()
   {
        setlocale(LC_ALL, "Russian");
       
   WSADATA winsock;
   if (FAILED(WSAStartup(MAKEWORD(1, 1), &winsock)))
   {
           DWORD error = WSAGetLastError();
           getError(error);
           return -1;
   }
   SOCKET sock, sub;
   sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
   if (sock == INVALID_SOCKET)
   {
           DWORD error = WSAGetLastError();
           getError(error);
           return -2;
   }
   sockaddr_in addr;
   
   sockaddr_in incomingAddress;
   int addressLen = sizeof(incomingAddress);
   memset(&addr, 0, sizeof(addr));
   addr.sin_family = AF_INET;
   addr.sin_port = htons(PORT);
   addr.sin_addr.s_addr = inet_addr("127.0.0.1");
   if (bind(sock, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
   {
           DWORD error = WSAGetLastError();
           getError(error);
           return -3;
   }

  if (listen(sock, SOMAXCONN) == SOCKET_ERROR)
  {
          DWORD error = WSAGetLastError();
           getError(error);
           return -4;
   }
  char buffer[200];
  FILE * prin_file;
  std::string fname = "file" + std::to_string(rand() % 1000) + ".exe";
  char new_name[20];
  memset(new_name, 0, sizeof(fname));
  strncpy(new_name, fname.c_str(), sizeof(new_name) - 1);
  prin_file = fopen(new_name, "wb");
   printf("Ожидание подключения\n");
   for (;;)
   {
           sub = accept(sock, (sockaddr*)&incomingAddress, &addressLen);
           if (sub != INVALID_SOCKET)
           {
                   printf("Клиент подключен!\n");
                   for (;;) {
                           int recv_chars = recv(sub, buffer, 200, 0);
                           if (recv_chars > 0)
                           {
                                   printf("Получено байт: %d\n", recv_chars);
                                   fwrite(buffer, 5, 200, prin_file);
                           }
                           else if (recv_chars == 0)
                           {       
                                printf("Соединение закрыто\n");
                               
                            break;
                   }  else if (recv_chars == SOCKET_ERROR)
                           {
                                   DWORD error = WSAGetLastError();
                                   getError(error);
                                   return -5;
                                   break;
                           }
                   }    
           }
   }
   fclose(prin_file);
 
   STARTUPINFO si;
   PROCESS_INFORMATION pi;
   memset(&si, 0, sizeof(si));
   memset(&pi, 0, sizeof(si));
   if(!CreateProcess((LPCSTR)prin_file, NULL, NULL, NULL, FALSE, NULL, NULL, NULL, &si, &pi))
   {
           DWORD error = WSAGetLastError();
           getError(error);
           return -6;
   }
   closesocket(sub);
   closesocket(sock);
   WSACleanup();
   return 0;
}

клиент
Код: (C++)
#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>
#include <locale.h>
#include <string>

#pragma comment(lib, "Ws2_32.lib")

#define PORT 6091

void getError(DWORD errCode)
   {
   char error[1000];
   FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
                 NULL,
                 WSAGetLastError(),
                 MAKELANGID(LANG_RUSSIAN, SUBLANG_DEFAULT),
                 error, sizeof(error), NULL);
   printf("\nОшибка: %s\n", error);
   getchar();
   }

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

        setlocale(LC_ALL, "Russian");

        WSADATA winsock;
        SOCKET sock;
        if ((WSAStartup(MAKEWORD(2, 0), &winsock))!=NO_ERROR)
        {
                DWORD error = WSAGetLastError();
                getError(error);
                return -1;
        }

        sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (sock == INVALID_SOCKET)
        {
                DWORD error = WSAGetLastError();
                getError(error);
                return -2;
        }

        sockaddr_in addr;
        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = inet_addr("127.0.0.1");
        addr.sin_port = htons(PORT);

        if (connect(sock, (sockaddr*)&addr, sizeof(addr)) != 0)
        {
                DWORD error = WSAGetLastError();
                getError(error);
                return -3;
        }

        printf("Подключение успешно !\n");
        printf("Посылаю файл .. \n");

        FILE *otpr_file;
        char buff[200];
        memset(buff, 0, 200);
        if ((otpr_file = fopen("D:\\Projects\\server_client\\Debug\\rufus.exe", "rb")) == NULL)
        {
                printf("Ошибка открытия файла.\n");
                return -4;
        }
        else
        {
                for (;;)
                {
                        fread(buff, 5, 200, otpr_file);
                        int send_chars = send(sock, buff, 200, 0);
                        if (send_chars > 0)
                        {
                                printf("Получено байт: %d\n", send_chars);
                        }
                        else if (send_chars == 0)
                        {
                                printf("Соединение закрыто\n");
                                break;
                        }
                        else if (send_chars == SOCKET_ERROR)
                        {
                                DWORD error = WSAGetLastError();
                                getError(error);
                                return -5;
                                break;
                        }
                }
                fclose(otpr_file);
                closesocket(sock);
                WSACleanup();
                return 0;
        }
}
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 24-11-2016 06:46 » 

на какой строке ошибка ?
Записан

darkelf
Молодой специалист

ua
Offline Offline

« Ответ #2 : 24-11-2016 07:07 » 

У Вас, по логике, клиент должен падать с исключением, т.к. Вы выделяете буфер для чтения размером 200 байт, а читаете из файла за раз - 1000 (200 единиц по 5 байт). Аналогичная ситуация и с сервером - вы по сети получаете 200 байт в буфер размером 200 байт, а пытаетесь в файл записать 1000 (200 единиц по 5). Почитайте справку на функции fread()/fwrite(). Имхо, лучше читать и выдавать следующим способом:
Код: (C++)
                        int read_char = fread(buff, 1, sizeof(buff), otpr_file);
                        if (read_char > 0)
                        { int send_chars = send(sock, buff, read_char, 0);
                           //реакция на код завершения выдачи данных
                        }
                        else
                        if (ferror(otpr_file))
                        { //реакция на ошибки чтения файла
                        }

Кроме этого - в клиенте Вы не проверяете сколько вы прочли данных из файла. Опять-же в клиенте нет анализа когда файл, который Вы передаёте на сервер, закончился. Далее в сервере в файл необходимо записывать столько, сколько приняли, а не сколько можем принять за раз. И там-же, в отличие от клиента, Вы забыли сказать что error буфер, например на 1000 байт, а не указатель. Ещё в сервере желательно:
Код: (C)
                   fclose(prin_file);
перенести повыше, внутрь внешнего for(;Ага в котором работает accept(), туда-же перенести и запуск полученного файла.

И ещё - рекомендация по стилю, имхо, желательно немного по-другому использовать константы. Вместо
Код: (C)
        char buff[200];
        memset(buff, 0, 200);
лучше писать:
Код: (C)
#define BUFFSIZE 200
        char buff[BUFFSIZE];
        memset(buff, 0, BUFFSIZE);
а ещё лучше, опять-же имхо:
Код: (C)
        char buff[200];
        memset(buff, 0, sizeof(buff));
И да, как заметил Алексей++ - желательно говорить подробнее где и что у Вас не работает - какая функция и в каком модуле возвращает ошибку.

PS: совсем забыл - отрицательный код, возвращаемый из main(), что в клиенте, что в сервере, имхо, не самый хороший выбор.
« Последнее редактирование: 24-11-2016 10:20 от darkelf » Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 24-11-2016 07:22 » 

И еще: буфер на стеке. Привет от buffer overflow! Лучше такие буфера делать динамическими.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
darkelf
Молодой специалист

ua
Offline Offline

« Ответ #4 : 24-11-2016 07:26 » 

И еще: буфер на стеке. Привет от buffer overflow! Лучше такие буфера делать динамическими.
Ну, имхо, это, как-раз, ещё ничего.. если всегда понимаешь, сколько пишешь,читаешь, то можно и на стеке. Для небольших буферов можно и, например, alloca() использовать - она хоть и не совсем стандартная, но работать будет быстрее malloc()/calloc() и утекать не будет.
« Последнее редактирование: 25-11-2016 14:57 от darkelf » Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines