powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как разделить сообщения на клиент сервере
60 сообщений из 60, показаны все 3 страниц
Как разделить сообщения на клиент сервере
    #38508743
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Реализую клиет сервер на основе функций из
winsock2.h

Долго не мог понять в чем проблема но получается что если сразу сделать две отправки от клиента к серверу или наоборот

что то типо
Код: plaintext
1.
2.
send(my_sock, sHELLO, sizeof(sHELLO), 0);
send(my_sock, sHELLO1, sizeof(sHELLO1), 0);



то сообщение как бы объединяется в одно, иногда все ок получается два отдельных сообщения, но иногда так иногда не так это конечно проблема.

Как можно однозначно разделить сообщения на разные ?
Есть какие то средства в winsock2 или единственный путь придумывать какой то свой разделитель?
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38508746
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
trom,

Это стандартное поведение TCP сокетов.
TCP это транспорт который доставляет поток байтов. Он не разделяет этот поток на сообщения.
Вам надо на уровне приложения уметь различать разные сообщения. Например перед каждым сообщением записывать в сокет его длину.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38508768
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly Moskovsky,

А можно пример на с++, как записывать и считывать ?
Длинна же может быть из одной цифры, а может из трех итд
Какое то стандартное решение для этого наверняка уже есть, не хотелось бы сочинять свои велосипеды в такой важной части кода как клиент сервер.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38508774
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tromДлинна же может быть из одной цифры, а может из трех итд
Раз у тебя протокол текстовый, то делай текстовый разделитель посылок. Обычно в таких
случаях используется символ конца строки.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38508775
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tromКакое то стандартное решение для этого наверняка уже есть, не хотелось бы
сочинять свои велосипеды в такой важной части кода как клиент сервер.
Почитай RFC по протоколам HTTP, SMTP, POP3. Там как раз описано стандартное решение.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38508781
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
trom,

примерно так (если без обработки ошибок)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
// send
int len = sizeof(sHELLO);
send(my_sock, (const char*)&len, sizeof(len), 0);
send(my_sock, sHELLO, sizeof(sHELLO), 0);

//receive
int len;
recv_all(my_sock, (char*)&len, sizeof(len)));
buf = new char[len];
recv_all(my_sock, buf, len));



recv_all - это написанная вами функция, которая в цикле вызывает стандартную recv пока из сокета не будет прочитано ровно len байтов
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38508816
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly Moskovsky,

Стандартный recv у меня уже в цикле while ждет сообщений

Код: plaintext
1.
2.
3.
	int bytes_recv;
	while ((bytes_recv = recv(my_sock, &buff[0], sizeof(buff), 0)) && bytes_recv != SOCKET_ERROR)
	{}



То есть идея как я понял такая, преобразованная в строку переменная типа int имеет стандартную длину, сначала считываться значение int, а потом преобразуется из строки обратно в int и уже считывается само сообщение ?

непойму если эта часть
Код: plaintext
1.
(const char*)&len

преобразует int в строку, то как из строки получить значение типо int ?
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38508820
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly Moskovsky,

Вернее даже так как из начала строки прочитать количество символов равным
int len;
sizeof(len);

и преобразовать полученный результат в обычное число int.
и прочитать часть строки от значения sizeof(len) до числа полученного из int.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38508854
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tromСтандартный recv у меня уже в цикле while ждет сообщений

Код: plaintext
1.
2.
3.
	int bytes_recv;
	while ((bytes_recv = recv(my_sock, &buff[0], sizeof(buff), 0)) && bytes_recv != SOCKET_ERROR)
	{}




Еще раз: recv не читает сообщения. Он читает поток байтов кусками случайной длины.
Поэтому чтобы прочесть например int который является 4-мя байтами, вам нужно вызывать в цикле recv пока не будут прочитаны ровно 4 байта. Не больше не меньше.
Поэтому ваш цикл с recv не годится.
Как я выше сказал, напишите функцию recv_all и используйте ее для чтения фиксированного кол-ва байтов.

Например так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
int recv_all(SOCKET s,  char* buf, int len)
{
   int total_recv = 0;
   int bytes_recv;
   while (len > 0 && (bytes_recv = recv(s, buf + total_recv , len, 0) > 0) {
      total_recv+= bytes_recv;
      len -= bytes_recv;
   }
   return total_recv;
}




tromнепойму если эта часть
Код: plaintext
1.
(const char*)&len

преобразует int в строку, то как из строки получить значение типо int ?
Тут нет преобразования в строку. Тут бинарное представление int рассматривается как массив char.
Такие базовые вещи С/С++ надо бы уже знать прежде чем писать сетевые программы.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38508917
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tromКакое то стандартное решение для этого наверняка уже есть, не хотелось бы сочинять свои велосипеды в такой важной части кода как клиент сервер.
Почитай про ZMQ .
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38508957
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
топикстартеру: еще раз, есть два протокола основных передачи данных в TCP/IP: UDP и TCP.

UDP пакетный, там есть пакеты и ты посылаешь и получаешь пакеты, но правда порядке пакетов не гарантирован и доставка тоже не обязательна.

TCP - наоборот, потоковый. пакетов нет, но доставка гарантирована. потоковый - это как любой файл или поток ввода/вывода: читаешь байтик за байтиком, и все.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38509084
kolobok0
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
trom...Долго не мог понять в чем проблема но получается что если сразу сделать две отправки от клиента к серверу или наоборот....или единственный путь придумывать какой то свой разделитель?


Офф/2:
Поздравляю! Вы один из не многих, кто увидел грабли в листве. Многие присыпают листвой потолще, у кого-то широкий шаг(в смысле тестирования не увидели)...

Тут всё верное прозвучало выше. TCP - потоковый. Ответ на Ваш вопрос становится очевиден, если представить как течёт поток воды и Вам надо отделять одну молекулу от другой. Но в сокетах немного попросче - Вы можете задавать строгую последовательность нескольких молекул(не встречающихся в основном потоке) - т.е. некий префикс вашему кванту. Либо заранее знать сколько Вы хотите получить на приёме. Для этого, обычно всегда передают заголовок(а на приёмной стороне он всегда гарантировано будет принят и он не делим) и из него знают длину хвоста идущего за ним.

Ну или как тут уже прозвучало - поменять протокол. Но Это всё-же похоже не для Вашей задачи...

удачи Вам
(круглый)
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38509235
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly Moskovsky,

Пример не рабочий.
Сижу разбираюсь целый день, тут какая то сложная работа с указателями пока я даже логику понять не могу.

А можно написать пример который будет работать ?
то есть есть две отправки первая это длинна сообщения, вторая это само сообщение и получатель должен получив сначала длину корректно прочитать основное сообщение

К примеру функция
recv_all(SOCKET s, char* buf, int len)
зависает при выполнении первый send вроде выводит но получает что то непонятное вроде знаков ====, а второй до конца обработать не может
Что и как править я разобраться не могу.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38509275
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
trom,

Придумывать и отлаживать код за вас лень.
Давайте вы приведете ваш код, а мы скажем что поправить.
А то иди знай что у вас не работает, может вы неправильные аргументы передаете. Телепаты в отпуске.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38509287
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly Moskovsky,

Ок тогда просто скину весь код клиент сервера с кодом из вашего примера

Как понимаю нужно править только клиент и его способ получения данных в нем вся проблема, а если отладить получение на клиенте то просто вставить ту же функцию на сервер и все.

Клиент
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
#include <iostream>
#include <stdio.h>
#include <winsock2.h> // Wincosk2.h должен быть раньше windows!
#include <windows.h>

#include <iostream>
#include <conio.h>


using namespace std; 

#define MAX_PACKET_SIZE         65535

int otpravka_dannih_na_Server(char* ip, int port, char* dannie_dla_vihoda, string dannie_dla_otpravki);
int recv_all(SOCKET s,  char* buf, int len);
int main()
{

	char* ip="127.0.0.1";
	int port=5050;
	char dannie_dla_vihoda[]="quit";
	string dannie_dla_otpravki;



	printf("TCP DEMO CLIENT\n");


    dannie_dla_otpravki="DANNIE\n";
	otpravka_dannih_na_Server(ip, port, dannie_dla_vihoda, dannie_dla_otpravki);


	return -1;

}

int otpravka_dannih_na_Server(char* ip, int port, char* dannie_dla_vihoda, string dannie_dla_otpravki){



	char            buff[MAX_PACKET_SIZE];
	char  *          buff2;
	// Шаг 1 - инициализация библиотеки Winsock
	if (WSAStartup(0x202, (WSADATA *)&buff[0]))
	{
		printf("WSAStart error %d\n", WSAGetLastError());
		return -1;
	}

	// Шаг 2 - создание сокета
	SOCKET my_sock;
	my_sock = socket(AF_INET, SOCK_STREAM, 0);
	if (my_sock < 0)
	{
		WSACleanup();
		printf("Socket() error %d\n", WSAGetLastError());
		return -1;
	}

	// Шаг 3 - установка соединения
	// заполнение структуры sockaddr_in - указание адреса и порта сервера
	sockaddr_in dest_addr;
	dest_addr.sin_family = AF_INET;
	dest_addr.sin_port = htons(port);
	HOSTENT *hst;
	dest_addr.sin_addr.s_addr = inet_addr(ip);

	// адрес сервера получен - пытаемся установить соединение
	if (connect(my_sock, (sockaddr *)&dest_addr, sizeof(dest_addr)))
	{
		closesocket(my_sock);
		WSACleanup();
		printf("Connect error %d\n", WSAGetLastError());
		return -1;
	}


	printf("Soedinenie s %s uspeshno ustanovlenno\n \
		   Type quit for quit\n\n", ip);

	// Шаг 4 - Прием и отправка сообщений
	// передаем строку клиента серверу
	int ret=0, i=0;
	
	int len;
	len=recv_all(my_sock, (char*)&len, sizeof(len));
	printf ("len= %d", len);

	buff2 = new char[len];
	for (i = 0; i<len; i++){printf ("%c", buff2 [i]);}

	recv_all(my_sock, buff, len);
	printf ("222len= %d\n", len);
	for (i = 0; i<len; i++){printf ("%c", buff [i]);}


	printf("Recv error %d\n", WSAGetLastError());
	closesocket(my_sock);
	WSACleanup();
	return -1;

}



int recv_all(SOCKET s,  char* buf, int len)
{
	int total_recv = 0;
	int bytes_recv;
	int i=0;

	//while ((nsize = recv(my_sock, &buff[0], sizeof(buff) - 1, 0)) != SOCKET_ERROR)
	while (len > 0 && (bytes_recv = recv(s, buf + total_recv , len, 0) > 0)) {

		printf ("f=%c\n", buf [i]);
		i++;
		total_recv+= bytes_recv;
		len -= bytes_recv;
	}

	printf ("END \n");


	return total_recv;
}



Сервер

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
#include <iostream>
#include <stdio.h>
#include <winsock2.h> // Wincosk2.h должен быть раньше windows!
#include <windows.h>
#include <process.h>
using namespace std; 
#define MY_PORT 5050 // Порт, который слушает сервер 666
#define MAX_PACKET_SIZE         65535



// макрос для печати количества активных пользователей
#define PRINTNUSERS if (nclients) printf("%d User on-line\n", nclients); \
        else printf("No User on line\n");

// прототип функции, обслуживающий подключившихся пользователей
unsigned __stdcall SexToClient(void* client_socket);

// глобальная переменная - количество активных пользователей
int nclients = 0;

int main()
{
char buff[MAX_PACKET_SIZE]; // Буфер для различных нужд
 
    printf("TCP SERVER DEMO\n");
    // Шаг 1 - Инициализация Библиотеки Сокетов
    // т.к. возвращенная функцией информация не используется
    // ей передается указатель на рабочий буфер, преобразуемый к указателю
    // на структуру WSADATA.
    // Такой прием позволяет сэкономить одну переменную, однако, буфер
    // должен быть не менее полкилобайта размером (структура WSADATA
    // занимает 400 байт)
    if (WSAStartup(0x0202, (WSADATA *)&buff[0]))
    {
        // Ошибка!
        printf("Error WSAStartup %d\n", WSAGetLastError());
        return -1;
    }
    // Шаг 2 - создание сокета
    SOCKET mysocket;
    // AF_INET - сокет Интернета
    // SOCK_STREAM - потоковый сокет (с установкой соединения)
    // 0 - по умолчанию выбирается TCP протокол
    if ((mysocket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        // Ошибка!
        printf("Error socket %d\n", WSAGetLastError());
        WSACleanup(); // Деиницилизация библиотеки Winsock
        return -1;
    }
 
    // Шаг 3 - связывание сокета с локальным адресом
    sockaddr_in local_addr;
    local_addr.sin_family = AF_INET;
    local_addr.sin_port = htons(MY_PORT); // не забываем о сетевом порядке!!!
    local_addr.sin_addr.s_addr = 0; // сервер принимает подключения
                                    // на все свои IP-адреса
 
    // вызываем bind для связывания
    if (bind(mysocket, (sockaddr *)&local_addr, sizeof(local_addr)))
    {
        // Ошибка
        printf("Error bind %d\n", WSAGetLastError());
        closesocket(mysocket); // закрываем сокет!
        WSACleanup();
        return -1;
    }
 
    // Шаг 4 - ожидание подключений
    // размер очереди - 0x100
    if (listen(mysocket, 0x100))
    {
        // Ошибка
        printf("Error listen %d\n", WSAGetLastError());
        closesocket(mysocket);
        WSACleanup();
        return -1;
    }
 
    printf("ozidanie podkluceniy...\n");
 
    // Шаг 5 - извлекаем сообщение из очереди
    SOCKET client_socket; // сокет для клиента
    sockaddr_in client_addr; // адрес клиента (заполняется системой)
 
    // функции accept необходимо передать размер структуры
    int client_addr_size = sizeof(client_addr);
 
    // цикл извлечения запросов на подключение из очереди
    while ((client_socket = accept(mysocket, (sockaddr *)&client_addr, &client_addr_size)))
    {
        nclients++; // увеличиваем счетчик подключившихся клиентов
 
        // пытаемся получить имя хоста
        HOSTENT *hst;
        hst = gethostbyaddr((char *)&client_addr. sin_addr.s_addr, 4, AF_INET);
 
        // вывод сведений о клиенте
        //printf("+%s [%s] new connect!\n",(hst) ? hst->h_name : " ", inet_ntoa(client_addr.sin_addr));
        PRINTNUSERS
 
        // Вызов нового потока для обслужвания клиента
        // Да, для этого рекомендуется использовать _beginthreadex
        // но, поскольку никаких вызовов функций стандартной Си библиотеки
        // поток не делает, можно обойтись и CreateThread
        unsigned int thID;
        //CreateThread(NULL, NULL, SexToClient, &client_socket, NULL, &thID);
		 _beginthreadex(NULL, NULL, SexToClient, &client_socket, NULL, &thID);
    }
    return 0;
}






// Эта функция создается в отдельном потоке 
// и обсуживает очередного подключившегося клиента независимо от остальных 
     unsigned __stdcall SexToClient(void* client_socket)
{

	char dannie_dla_vihoda[MAX_PACKET_SIZE];
	strcpy(dannie_dla_vihoda, "quit");


    SOCKET my_sock;
    my_sock = ((SOCKET *)client_socket)[0];
    char buff[MAX_PACKET_SIZE];//char buff[20 * 1024];
 
	#define sHELLO "HELLO\n"

	int len = sizeof(sHELLO);
	send(my_sock, (const char*)&len, sizeof(len), 0);
	send(my_sock, sHELLO, sizeof(sHELLO), 0);


	int bytes_recv, i;
	char temp[MAX_PACKET_SIZE];
	while ((bytes_recv = recv(my_sock, &buff[0], sizeof(buff), 0)) && bytes_recv != SOCKET_ERROR)
	{

		buff[bytes_recv] = 0;
	
		// выводим на экран
		printf("OT CLIENTA=\n");
		for (i = 0; i<bytes_recv; i++){printf ("%c", buff [i]);}


		// проверка на "quit"
		if (!strcmp(&buff[0], dannie_dla_vihoda))
		{
				
			/////OTPRAVKA VIHODA DLA CLIENTA
			send(my_sock, dannie_dla_vihoda, sizeof(dannie_dla_vihoda), 0);
			printf("SERVER OTPRAVIL=%s\n", dannie_dla_vihoda);
			/////OTPRAVKA VIHODA DLA CLIENTA
		
		}


	}
		
		
    // если мы здесь, то произошел выход из цикла по причине
    // возращения функцией recv ошибки - соединение с клиентом разорвано
    nclients--; // уменьшаем счетчик активных клиентов
    printf("-disconnect\n"); PRINTNUSERS
 
    // закрываем сокет
    closesocket(my_sock);
	//WSACleanup();

   return 0;


}
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38509293
wst
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
        /// Вот эти вот 2 строчки
	buff2 = new char[len];
	for (i = 0; i<len; i++){printf ("%c", buff2 [i]);}


Выводят мусор еще до попытки получения данных пакета. Какой смысл выводить что там в свежевыделенной памяти валяется? Особенно когда buff2 нигде не используется и не освобождается.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38509298
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
wst,

делать то что?
удалить их?
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38509398
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот это
Код: plaintext
1.
while (len > 0 && (bytes_recv = recv(s, buf + total_recv , len, 0) > 0))


заменить на
Код: plaintext
1.
while (len > 0 && (bytes_recv = recv(s, buf + total_recv , len, 0)) > 0)



Кроме того, как выше сказали, это бессмысленный кусок кода, выводящий мусор.
Код: plaintext
1.
2.
	buff2 = new char[len];
	for (i = 0; i<len; i++){printf ("%c", buff2 [i]);}



Кроме того, если вы передаете длину сообщения, то это нужно делать везде, а не по желанию, в том числе и в серверной части.

Кроме того, после комментария
Код: plaintext
1.
	// передаем строку клиента серверу


у вас только код принимающий данные, т.е. комментарий противоречит коду.
Но это ладно. А вот, хоть сервер и пытается читать с клиента, но клиент ни разу ничего не отправляет.

Как поправите эти очевидные баги, приводите очередной вариант кода, будем смотреть дальше.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38509493
kolobok0
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Выше правильно уже прозвучали необходимые доработки...
свои 5 копеек...
trom
...
Сервер

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
....        // Вызов нового потока для обслужвания клиента
        // Да, для этого рекомендуется использовать _beginthreadex
        // но, поскольку никаких вызовов функций стандартной Си библиотеки
        // поток не делает, можно обойтись и CreateThread
        unsigned int thID;
        //CreateThread(NULL, NULL, SexToClient, &client_socket, NULL, &thID);
		 _beginthreadex(NULL, NULL, SexToClient, &client_socket, NULL, &thID);
    }
    return 0;
}
...





данная увязка потоков быдет плыть при ударных нагрузках на сервак. И в случаи аварийных остановов или быстрое внешняя попытка отгрузки программы в некоторых случаях будет приводить к очень интересным поведениям. Или по другому...
Т.к. при вызове бегинсреад потоку ещё управление не передалось, и в случае короткого времени жизни приложения вообще не передастся, и Вам пофигу: начала работу ниточка или нет - предлагаю вообще нитку не запускать (в некоторых случая так оно и будет).

и ышо...
то что у вас и приветная и ответная части обе слушают - то ничего не будет(это уже прозвучало выше). Обратите внимание как слушает клиент. Что он ожидает (длину данных и тип), и что делает после этого. Ответная часть(в частности сервак) должен именно так(и такие размерности) и послать данные...

удачи вам
(круглый)
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38509559
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly Moskovsky,

Код заменил теперь вроде ничего не зависает и передается, но я не могу понять как извлечь из
Код: plaintext
1.
len=recv_all(my_sock, (char*)&len, sizeof(len));


значение длинны последующего сообщения ведь тут в функцию не передается массив char, тут у нас (char*)&len

Код: plaintext
1.
2.
recv_all(my_sock, buff, len);
for (i = 0; i<5; i++){printf ("%c", buff [i]);}


А этот код работает но значение длинны сообщения 5 я поставил сам
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38509561
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kolobok0,

Не понял предлагаете не использовать _beginthreadex( и сделать просто последовательный сервер ?
или я его как то не так использую ?

В примере клиент сервера на котором я основывался была функция CreateThread про которую писали что лучше ее заменить на _beginthreadex (так как у меня просто консольное приложение), я и заменил.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38509565
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
trom
Код: plaintext
1.
len=recv_all(my_sock, (char*)&len, sizeof(len));


Тут вы читаете из сокета int в переменную len и тут же затираете его, присваивая возвращаемое значение recv_all (сколько байтов прочитано) в ту же переменную len.
Используйте разные переменные для этих двух длин.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38509975
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tromтут в функцию не передается массив char
Несмотря на то, что параметр функции объявлен как char*, функция работает с любым
указателем, поскольку ей не нужно интерпретировать массив байт. Если хотите, можете
полезть в заголовочные файлы и заменить тип этого параметра на void*. Может, тогда в Вашем
мозгу что-нибудь прояснится.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38510003
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly Moskovsky,

Все наконец заработало спасибо!

только я непойму а как сделать цикл типа while который ждал бы сообщений в бесконечном цикле

то есть нужно что то типо
Код: plaintext
1.
2.
while ((bytes_recv = recv(my_sock, &buff[0], sizeof(buff), 0)) && bytes_recv != SOCKET_ERROR)
	{



Но с использованием вашей функции recv_all
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38510074
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
trom,

nclients--; // уменьшаем счетчик активных клиентов

У тебя доступ к этой переменной из разных потоков без синхронизации.
Будут гонки ( rase conditions ).

Тебе надо защищать доступ к этой переменной мьютексом или критической секцией.
Конкретно здесь лучше всего заменить изменение переменной на InterlockedIncrement/Decriment

msdn.microsoft.com/en-us/library/windows/desktop/ms683614(v=vs.85).aspx
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38510100
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
trom,

по переменной client_socket у тебя тоже будут гонки.
Она также незащищена ничем.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38510116
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
trom,

Ты так же везде шлёшь бинарку, т.е. у тебя нифига не текстовый протокол, но буфера все печатаешь как симпольные, printf-ом.

Плохо кончится.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38510153
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну и вообще дофига других ошибок дурацких.
Любая из них может привести всё в неработоспособное состояние.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38510196
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv,

переменную
nclients--; // уменьшаем счетчик активных клиентов
можно и удалить, она не очень важна

printf тоже только в режиме отладки нужен


А вот client_socket важна, с много поточностью почти не работал, можно пример в коде что с ней можно сделать чтобы не было проблем ?
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38510261
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tromчто с ней можно сделать чтобы не было проблем ?
Передавать её в поток по значению, а не по ссылке.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38510276
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakovtromчто с ней можно сделать чтобы не было проблем ?
Передавать её в поток по значению, а не по ссылке.


+1
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38510594
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv,

Как именно передать ее по значению?
Код: plaintext
1.
_beginthreadex(NULL,NULL,SexToClient,&client_socket,NULL,&thID);


компилируется

Код: plaintext
1.
_beginthreadex(NULL,NULL,SexToClient,client_socket,NULL,&thID);


уже нет

то есть client_socket можно передать только по ссылке
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38510946
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tromMasterZiv,

Как именно передать ее по значению?
Код: plaintext
1.
_beginthreadex(NULL,NULL,SexToClient,&client_socket,NULL,&thID);


компилируется

Код: plaintext
1.
_beginthreadex(NULL,NULL,SexToClient,client_socket,NULL,&thID);


уже нет

то есть client_socket можно передать только по ссылке
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38511071
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tromКак именно передать ее по значению?
RTFM typecast
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38511108
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovtromКак именно передать ее по значению?
RTFM typecast


дам подсказку :
этот параметр потока на самом деле не указатель, а просто машинное слово.
ос его не отрабатывает, а в неизменном виде передает функции потока.
главное, чтобы твои данные туда влезли.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38511232
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv,

Лучше в коде покажи как сделать, подсказка мне не помогла
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38511498
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
trom,

_beginthreadex(NULL,NULL,SexToClient,(void *)client_socket,NULL,&thID );

и на приемной стороне аналогичное преобразование в обратную сторону.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38511729
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv,

Код: plaintext
1.
_beginthreadex(NULL,NULL,SexToClient,(void *)client_socket,NULL,&thID );


вот так скомпилилось. Но при запуске клиент сервера, сервер зависает.
На приемной стороне это где ? внутри функции ?
Что делать то, можно пример как преобразовать в обратную сторону?
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38511828
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tromMasterZiv,

Код: plaintext
1.
_beginthreadex(NULL,NULL,SexToClient,(void *)client_socket,NULL,&thID );


вот так скомпилилось. Но при запуске клиент сервера, сервер зависает.
На приемной стороне это где ? внутри функции ?
Что делать то, можно пример как преобразовать в обратную сторону?

да, внутри функции потока.


обратное преобразование
socket = (int) thread_param;
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38512202
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
навараксал это всё по-нормальному...
получился такой полноценный Winsock-echo-server...
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38512513
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv,

Спасибо теперь понятно!
Чуть попозже выложу свой код клиент сервера попроще.

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

2) Как лучше сделать:
а) Клиент отправляет сообщение получает ответ и отсоеденяется .
б) Клиент постоянно подключен к серверу, все время работы программы клиента.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38512529
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivнавараксалчто сделал? ;)
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38512611
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1) Нужно ли выделять разные порты если на компе будут работать две и больше программы сервера ?


как бы на одном порту они просто не смогут работать.



2) Как лучше сделать:
а) Клиент отправляет сообщение получает ответ и отсоеденяется .
б) Клиент постоянно подключен к серверу, все время работы программы клиента.


б)
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38513535
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv,
Вынес подключение клиента к серверу в отдельную функцию и возник вопрос.
Для того чтобы клиент был подключен к серверу от начала запуска проги и до конца, если правильно понимаю переменную
Код: plaintext
1.
SOCKET mysocket;

нужно делать глобальной.
А как проверить что этой переменной уже присвоено какое то подключение к серверу ?
Чтобы сделать проверку о наличии подключения и если его нет или оно разорвано пере подключится.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38513565
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Для того чтобы клиент был подключен к серверу от начала запуска проги и до конца, если правильно понимаю переменную
Код: plaintext
1.
SOCKET mysocket;

нужно делать глобальной.


Нет, ты понимаешь неправильно.



А как проверить что этой переменной уже присвоено какое то подключение к серверу ?
Чтобы сделать проверку о наличии подключения и если его нет или оно разорвано пере подключится.



Сравнить её с "НУЛЁМ". Что для переменной SOCKET является нулём -- ещё вопрос, но я думаю, что если ты затрёшь её всю нулями, а после установки соединения проверишь, что там не всё нули, будет оно самое то.

Другой вариант -- переменную сделать указателем, проверять на NULL и выделять при установке соединения.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38513575
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть тут только одна маленькая фигня: разрыв соединения (по любой причине) не приводит к
автоматическому обнулению переменной на что надеется ТС.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38513608
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tromMasterZiv,
Вынес подключение клиента к серверу в отдельную функцию и возник вопрос.
Для того чтобы клиент был подключен к серверу от начала запуска проги и до конца, если правильно понимаю переменную
Код: plaintext
1.
SOCKET mysocket;

нужно делать глобальной.Неправильно.
Глобальность переменной для этого будет полезна, но она не гарантирует того что коннект будет существовать.

tromА как проверить что этой переменной уже присвоено какое то подключение к серверу ?Функция socket() возвращает -1 если она не смогла создать сокет. Поэтому обычно и переменную держат в этом значении чтобы показать что сокет не существует. Но это просто рекомендация.
В 0 ее ставить для несуществующего сокета не стоит - ноль это обычно stdout. Вполне существующий поток.

tromЧтобы сделать проверку о наличии подключения и если его нет или оно разорвано пере подключится.Проверяй результат который тебе возвращают все твои send()/recv(). Если они упали с ошибкой - читай номер ошибки. И если это ошибка отсутствия коннекта - подключайся заново.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38513613
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White OwlФункция socket() возвращает -1
Под виндой тип SOCKET - unsigned.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38513618
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyWhite OwlФункция socket() возвращает -1
Под виндой тип SOCKET - unsigned.Под виндой socket и WSASocket возвращают INVALID_SOCKET. Хочешь угадать чему оно равняется? :)
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38513620
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White Owl,

В доке прямо написано, что не следует предполагать что INVALID_SOCKET приводится к -1.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38513623
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyWhite Owl,

В доке прямо написано, что не следует предполагать что INVALID_SOCKET приводится к -1.Где это написано? Ткни пальцем пожалуйста.
А в winsock2.h есть строчка: #define INVALID_SOCKET (SOCKET)(~0)
Так чта... Оно конечно не -1 с точки зрения компилятора, но...
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38513634
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White OwlГде это написано? Ткни пальцем пожалуйста.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740516(v=vs.85).aspx
авторchecking for errors when the socket and accept functions return should not be done by comparing the return value with –1, or seeing if the value is negative (both common and legal approaches in UNIX). Instead, an application should use the manifest constant INVALID_SOCKET


White OwlА в winsock2.h есть строчка
Полагаться надо на АПИ, а не на детали реализации.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38513637
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl,
Anatoly Moskovsky,
MasterZiv,

Сейчас у себя потестил когда клиент подключается на не реальный ип адрес
Функция WSAGetLastError();
возвращает ошибку с кодом 10093
как при отправке так и при получении данных

То есть наметил такую схему программы
После первого подключения клиент при каждой отправке или получении данных ждет ошибку от WSAGetLastError(); с кодом 10093 и если ее получает то пытается подключиться по новой.

Все правильно или опять что не так понял ?
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38513650
wst
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Только не так. Соединяться можно и по-прежнему, а вот дальше считать любую ошибку от recv() поводом пересоздать соединение. И еще очень облегчит жизнь вынос приема-отправки сообщений в отдельную пару функций, которые сначала отладить на кошках, потом уже на их основе делать что клиента что сервера.
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38513679
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Начнем с того что ошибка 10093 никакого отношения к ИП адресам или ошибкам подключения не имеет.
Это WSANOTINITIALISED, что означает либо еще не вызван WSAStartup либо уже вызван WSACleanup, то есть сугубо криво написанная программа :)
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38514670
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Все сделал клиент с обработкой ошибок, покритикуйте!
Все разделено на отдельные функции чтобы было удобно применять в больших проектах, где всякие детали подключения и отправки только будут мешать.
В процессе работы сервер может пропадать и появляться в любое время, прога при пропаже сервака сразу начинает отсчет попыток подключиться, если сервер успевает появиться работает опять в нормальном режиме если нет завершает работу с ошибкой.
Ошибки обрабатываются при каждой отправке или получении данных и при первом подключении к серверу.
Можно задать максимальное количество попыток подключиться и паузу между попытками.

Ошибки обрабатываются просто, если она есть происходит пере подключение, хотя конечно они могут быть из за разных причин, но только эту можно обработать в программе, все остальное ошибки программиста.
Сначала хотел обрабатывать только ошибку 10054, но потом подумал пусть лучше при любой ошибки переподключается.

сервер выложу позже, как понимаю будет попроще, ошибки там обрабатывать не надо, сложности только в нюансах работы с много поточностью.


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
#include <iostream>
#include <stdio.h>
#include <winsock2.h> // Wincosk2.h должен быть раньше windows!
#include <windows.h>

#include <iostream>
#include <conio.h>
#include <fstream>

using namespace std; 

#define MAX_PACKET_SIZE         65535
char* ip="127.0.0.1";
int port=5050;
SOCKET my_sock;

int otpravka_i_polysenie_dannih_CLIENT(string dannie_dla_otpravki, int MAX_count_popitok, int PAUSE_mezdy_popitok);
int recv_all(SOCKET s,  char* buf, int len);
int  otpravka_soobsenia(string text_msg, int MAX_count_popitok, int PAUSE_mezdy_popitok);
int polychenie_soobsenia(char buff[MAX_PACKET_SIZE], int MAX_count_popitok, int &len, int PAUSE_mezdy_popitok);
int podklysenie_k_servery(int MAX_count_popitok, int PAUSE_mezdy_popitok);


int main()
{
	int count_popitok=0, MAX_count_popitok=5, PAUSE_mezdy_popitok=2000, result=1;
	string dannie_dla_otpravki;

	printf("TCP DEMO CLIENT\n");

	result=podklysenie_k_servery(MAX_count_popitok, PAUSE_mezdy_popitok);
	
	if(result==1){
	printf("Soedinenie s %s uspeshno ustanovlenno\n\n", ip);
    dannie_dla_otpravki="MSG OT KLIENTA \n";
	result=otpravka_i_polysenie_dannih_CLIENT(dannie_dla_otpravki, MAX_count_popitok, PAUSE_mezdy_popitok);
		}	

	
	if(result==-1){MessageBoxA(NULL, "Ошибка", "Работа с сервером завершена неудачно", MB_OK);}

	return -1;

}

int otpravka_i_polysenie_dannih_CLIENT(string dannie_dla_otpravki, int MAX_count_popitok, int PAUSE_mezdy_popitok){

	int result=1;

	char  buff[MAX_PACKET_SIZE];

	Sleep(10000);

	int ret=0, i=0;
	

	result=otpravka_soobsenia(dannie_dla_otpravki, MAX_count_popitok, PAUSE_mezdy_popitok);
	
	int len=0;

	if(result==1){
 	while(strcmp(buff, "quit")!=0){ 
 		for (i = 0; i<MAX_PACKET_SIZE; i++){buff[i]=0;}
 
 		result=polychenie_soobsenia(buff, MAX_count_popitok, len, PAUSE_mezdy_popitok);
 		for (i = 0; i<len; i++){printf ("%c", buff [i]);}
 
 		if(len>0&&result==1){	
       	result=otpravka_soobsenia("quit", MAX_count_popitok, PAUSE_mezdy_popitok);
		}
	
	if(result==-1){break;}
	}
	
	
	
	}

closesocket(my_sock);
WSACleanup();

Sleep(10000);

return result;
}
int podklysenie_k_servery(int MAX_count_popitok, int PAUSE_mezdy_popitok){

	int result=-1, count_popitok=0;
	char buff[MAX_PACKET_SIZE];


	while(result==-1&&count_popitok<=MAX_count_popitok){
		
		result=1;

	// Шаг 1 - инициализация библиотеки Winsock
	if (WSAStartup(0x202, (WSADATA *)&buff[0]))
	{
		printf("WSAStart error %d\n", WSAGetLastError());
		result=-1;
	}
	// Шаг 2 - создание сокета
	//SOCKET my_sock;
	my_sock = socket(AF_INET, SOCK_STREAM, 0);
	if (my_sock < 0)
	{
		WSACleanup();
		printf("Socket() error %d\n", WSAGetLastError());
		result=-1;
	}

	// Шаг 3 - установка соединения
	// заполнение структуры sockaddr_in - указание адреса и порта сервера
	sockaddr_in dest_addr;
	dest_addr.sin_family = AF_INET;
	dest_addr.sin_port = htons(port);
	HOSTENT *hst;
	dest_addr.sin_addr.s_addr = inet_addr(ip);

	// адрес сервера получен - пытаемся установить соединение
	if (connect(my_sock, (sockaddr *)&dest_addr, sizeof(dest_addr)))
	{
		closesocket(my_sock);
		WSACleanup();
		printf("Connect error %d\n", WSAGetLastError());
		result=-1;
	}
	
	if(result!=1){		
		closesocket(my_sock);
		WSACleanup();

		printf("Popitka soedinenia #%d neydasna\n", count_popitok);
		Sleep(PAUSE_mezdy_popitok);}
	
	if(count_popitok==MAX_count_popitok&&result==-1){MessageBoxA(NULL, "Ошибка", "Не удалось подключиться к серверу", MB_OK);}
	
	count_popitok++;
	
	}

	


return result;
}
int polychenie_soobsenia(char buff[MAX_PACKET_SIZE], int MAX_count_popitok, int &len, int PAUSE_mezdy_popitok){
	
	int result=1, wsaError=1, recv1=0, count=0;

	while(wsaError/*==10054*/){
		

		if(count>0){
			closesocket(my_sock);
			WSACleanup();
			result=podklysenie_k_servery(MAX_count_popitok, PAUSE_mezdy_popitok);}
		if(result==-1){break;}

	if(recv1==0){
	wsaError=recv_all(my_sock, (char*)&len, sizeof(len));
	if(wsaError){printf("\nRecv error1 %d\n", wsaError);}else{recv1=1;}
		}
	

	
	if(recv1==1){
	wsaError=recv_all(my_sock, buff, len);
	if(wsaError){printf("\nRecv error2 %d\n", wsaError);}
	}
	 
	count++;
	}


	return result;
}
int otpravka_soobsenia(string text_msg, int MAX_count_popitok, int PAUSE_mezdy_popitok){
	int result=1, wsaError=1;
	int len = text_msg.length();
	int send1=0, count=0;

	while(wsaError/*==10054*/){

		if(count>0){
			closesocket(my_sock);
			WSACleanup();
			result=podklysenie_k_servery(MAX_count_popitok, PAUSE_mezdy_popitok);}
		if(result==-1){break;}

	if(send1==0){//Чтобы небыло повторных отправок в случае успешной отправки первого сообщения и ошибки во втором
	send(my_sock, (const char*)&len, sizeof(len), 0);

	wsaError = WSAGetLastError();
	if(wsaError){printf("\nSend error1 %d\n", WSAGetLastError()); printf("result %d\n", result);}else{send1=1;}
	
	}

	if(send1==1){//Если первое сообщение успешно отправлено пытаемся отправить второе
	send(my_sock, text_msg.c_str(), len, 0);

	wsaError = WSAGetLastError();
	if( wsaError )
	{	printf("\nSend error2 %d\n", WSAGetLastError());
		
	}}
	
	 

	count++;
	}
	
	return result;
}
int recv_all(SOCKET s,  char* buf, int len)
{
	int total_recv = 0;
	int bytes_recv;
	int i=0;

	while (len > 0 && (bytes_recv = recv(s, buf + total_recv , len, 0)) > 0) {

		i++;
		total_recv+= bytes_recv;
		len -= bytes_recv;
	}


	return WSAGetLastError();
}
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38514723
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
trom,

Вот это вот


if (WSAStartup(0x202, (WSADATA *)&buff[0]))

что за порнография, а?
расскажи пожалуйста...
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38514835
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv,

да спасибо!
Я еще сам думал зачем при подключении массив char buff, заменил на кусок из твоего кода

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
	// Шаг 1 - инициализация библиотеки Winsock
	WSADATA wsadata;
	if( WSAStartup(0x202, &wsadata) )
	{
		printf("WSAStart error %d\n", WSAGetLastError());
		return -1;
	}



А так в целом все ок по коду ?
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38514836
trom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv,

кстати эту buff автор кода объясняет так

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
    // Шаг 1 - Инициализация Библиотеки Сокетов
    // т.к. возвращенная функцией информация не используется
    // ей передается указатель на рабочий буфер, преобразуемый к указателю
    // на структуру WSADATA.
    // Такой прием позволяет сэкономить одну переменную, однако, буфер
    // должен быть не менее полкилобайта размером (структура WSADATA
    // занимает 400 байт)
    if (WSAStartup(0x0202, (WSADATA *)&buff[0]))
    {
        // Ошибка!
        printf("Error WSAStartup %d\n", WSAGetLastError());
        return -1;
    }



то есть какая то экономия переменной, но при выносе подключения в отдельную функцию экономии никакой нет.
Да и что вообще за экономия переменной ? первый раз такое слышу
...
Рейтинг: 0 / 0
Как разделить сообщения на клиент сервере
    #38514856
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tromто есть какая то экономия переменной, но при выносе подключения в отдельную функцию экономии никакой нет.
Да и что вообще за экономия переменной ? первый раз такое слышуИзвращение это. Совершенно не нужное и более того - вредное.
Один из источников вредности ты только что увидел: буфер должен быть не менее полкилобайта размером. А если тебе буфер нужен меньшего размера, и ты его уменьшишь не заметив комментария в тексте - получишь либо GPF, либо плавающие ошибки в совершенно разных местах программы, которые будешь долго искать.
Ну и в именах переменных будешь путаться.


В принципе, если ты сидишь на машине с очень маленькой памятью, то это может быть полезным. Этакое "управляемое повторное использование ячеек памяти". Но в реальности такое нужно только на ОЧЕНЬ маленькой памяти. Я таким развлекался последний раз на МК-61, были такие программируемые калькуляторы с 15-ю ячейками памяти. Но уже на Специалисте, имевшем целых 48Кб ОЗУ и на ассемблере (где памятью управлять напрямую можно) осознал что такая экономия памяти может вылезти боком.
...
Рейтинг: 0 / 0
60 сообщений из 60, показаны все 3 страниц
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как разделить сообщения на клиент сервере
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]