Сокеты C ++ - Могу ли я отправлять только символы? - PullRequest
4 голосов
/ 11 августа 2010

Я использую синхронизированные сокеты с окном win32 и использую функции send () и recv () для отправки данных через интернет TCP;

Что мне интересно, как я мог бы отправить некоторые целые числа или даже мой собственный класс / структуру через сокет TCP? потому что функция send () позволяет мне отправлять только символы.

Должен ли я просто отправить символы и затем преобразовать их в целое число с помощью atoi ()? или если бы я хотел отправить структуру класса, я бы отправил много строк, а затем поместил бы их в переменные ... одну за другой.

Ответы [ 4 ]

5 голосов
/ 11 августа 2010

Он не отправляет символы в текстовом смысле - он отправляет непрерывные массивы байтов, к которым он обращается, используя символ *.Таким образом, вы можете указать на байты любого типа значения, так что если вы хотите отправить int,

int A = 5;
const char* pBytesOfA = (const char*)&A;
int lengthOfBytes = sizeof(A);

send(socket, pBytesOfA, lengthOfBytes, flags);
2 голосов
/ 11 августа 2010

Скорее не делайте этого сами, используйте библиотеки, которые делают это для вас, например Boost.Asio и Boost.Serialization .

Boost Asio - это библиотека, котораязаменяет сокеты и даже предоставляет интерфейс , такой как C ++ iostreams , и будет обрабатывать для вас встроенные типы отправки, такие как int.

Повышенная сериализация позволяет легко сериализовать ваши классы, чтобы вы могли отправлятьих по сети.

Если вы не можете использовать дополнительные библиотеки, вам придется отправлять данные вручную через обычные сокеты - убедитесь, что вы не забыли использовать htons, ntohs, htonl и ntohl функций, иначе ваш код сломается, когда два компьютера будут использовать разные порядковые номера (порядок байтов).

маленький фрагмент:

// sender:
unsigned long to_send = 123;
unsigned long to_send_n = htonl(to_send); // convert to network byte order
send(send_socket, (const char*)(&to_send_n), sizeof(unsigned long), flags);

// reciever:
char recv_buf[sizeof(unsigned long)];
recv(recv_socket, recv_buf, sizeof(unsigned long)); //recieve number
unsigned long recieved = ntohl(*((unsigned long*)recv_buf), flags); // convert back to host byte order

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

2 голосов
/ 11 августа 2010

Это зависит от того, что вы хотите сделать. Одна простая возможность:

Предположим, что int имеет 32 значащих бита и что отрицательные значения кодируются в виде дополнения до двух. Затем вы можете отправить один int как четыре chars:

bool send_int(int fd, int i)
{
  unsigned char buf[4];
  buf[0] = (i >> 24) & 0xff;
  buf[1] = (i >> 16) & 0xff;
  buf[2] = (i >>  8) & 0xff;
  buf[3] = (i >>  0) & 0xff;
  return ((unsigned) send(fd, buf, sizeof buf, 0) == sizeof buf);
}

На принимающей стороне вы должны прочитать четыре байта и затем объединить их значения, чтобы они снова образовали int.

Существует много других возможностей для кодирования int s и других типов данных в виде потока байтов. Выше приведен простой пример.

0 голосов
/ 11 августа 2010

AC (++) char - это не то же самое, что символ .char - это просто целочисленный тип, по крайней мере (и обычно точно) 8 бит.char часто действительно представляет символ ASCII (или в настоящее время кодовая единица UTF-8), но он также может представлять произвольные двоичные данные, как в случае send() и recv().

Теперь есть некоторые протоколы (например, SMTP), которые do предполагают, что данные являются текстовыми, и могут искажать двоичные данные, которые содержат байты, такие как 0x0A (перевод строки) или 0x00(C Строка терминатора).В этом случае вам нужно использовать двоичную кодировку, такую ​​как Base64.Но это не должно быть проблемой, если вы работаете с TCP напрямую.

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