powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как разделить сообщения на клиент сервере
25 сообщений из 60, страница 1 из 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
25 сообщений из 60, страница 1 из 3
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как разделить сообщения на клиент сервере
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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