User 13204940 Ответов: 1

Сокеты в C++ - отправка char* и char[]


Привет,

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

В любом случае, у меня есть несколько вопросов;

1. я не могу понять, как объединить char* и buf. Я также беспокоюсь о том, что это неэффективно, и это привело меня в замешательство.

2. Это наиболее эффективный способ обрабатывать входящие данные и отправлять данные? Это должно быть очень быстро, так как оно будет использоваться в производстве.

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

void send(SOCKET socket, const char* data)
{
	send(socket, data, sizeof(data), 0);
}

DWORD WINAPI receive_thread(LPVOID lpParam)
{
	SOCKET current_client = (SOCKET)lpParam;

	char buf[100];
	int res;

	// if buffer = 'hello': strstr(buf, "hello")

	// receive messages
	while (true)
	{
		res = recv(current_client, buf, sizeof(buf), 0); // read data

		Sleep(10);

		printf("Client said: %s", buf);
		Sleep(10);

		char* x = (char*)"You said: ";
		x += buf; // trying several things here, just isn't working
		strcpy_s(x, buf);
		send(current_client, x);
		
		// empty buffer
		strcpy_s(buf, "");
	}
}


Что я уже пробовал:

----------------------------------------------------------------

1 Ответов

Рейтинг:
0

Jochen Arndt

Ваши проблемы и ошибки не связаны с сокетом, но связаны с базовыми знаниями языка Си.

Это приведет к отправке 4 или 8 байт в зависимости от сборки (32 или 64 бит), потому что sizeof() for a pointer возвращает размер указателя, а не каких-либо данных (он расширяется во время компиляции и не обрабатывается во время выполнения):

void send(SOCKET socket, const char* data)
{
    send(socket, data, sizeof(data), 0);
}

Это требует, чтобы строка была отправлена, включая завершающий нулевой символ.
res = recv(current_client, buf, sizeof(buf), 0); // read data
printf("Client said: %s", buf);
Чтобы убедиться, что строка завершается NULL, вы можете использовать
buf[min(sizeof(buf) - 1, res)] = 0;

Это очень вероятно приведет к катастрофе:
char* x = (char*)"You said: ";
x += buf; // trying several things here, just isn't working
strcpy_s(x, buf);
send(current_client, x);
Добавление указателей не добавит содержимое и не отбросит константу памяти, на которую указывает x это приводит к нарушению доступа. Ваш код-это простой C, а не строковый Класс C++, где это обычно возможно. Вы должны использовать другой буфер для подготовки и отправки строки:
char txbuf[100];
strcpy_s(txbuf, "You said: ");
// Requires that buf is NULL terminated (see above)
strcat_s(txbuf, buf);
// Send including the NULL byte
send(current_client, txbuf, strlen(txbuf) + 1, 0);
или как C++ с помощью std::string
std::string txbuf("You said: ");
// The std::string class supports appending with the += operator
txbuf += buf;
// Send including the NULL byte
send(current_client, txbuf.c_str(), txbuf.length() + 1, 0);


[no name]

Спасибо вам, пример с char txbuf[100] сработало, но мне только нужно было strlen(txbuf), нет strlen(txbuf) + 1

Причина, по которой я держался подальше от std::string, заключается в том, что у него есть небольшие накладные расходы, которых я хотел избежать, чтобы сделать его максимально эффективным.

Я не имел в виду, что сокеты были проблемой, я имел в виду, что это было на тему сокетов, с которыми у меня было несколько проблем.

Jochen Arndt

Если вы отправляете без завершающего нулевого байта, вы должны добавить его на принимающей стороне, как показано в моем решении, прежде чем использовать любую строковую функцию библиотеки C, такую как printf (), strcpy () или strcat().
Отправка нулевого байта гарантирует нулевые завершенные строки на случай, если вы забудете это сделать. Это также станет необходимым, когда вам придется передавать данные, превышающие размер сетевого пакета, чтобы обнаружить конец пакета. Но тогда использование "протокола", содержащего длину пакета, гораздо лучше и профессиональнее.