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

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

ru
Online Online
Пол: Мужской

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