Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.89/9: Рейтинг темы: голосов - 9, средняя оценка - 4.89
7 / 7 / 2
Регистрация: 26.12.2011
Сообщений: 269

Прием данных клиентом TcpClient, данных попадается некорректные значения, почему?

14.11.2015, 14:56. Показов 2165. Ответов 19
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть сервер на си, который шлет ответ клиенту, вот тестовый кусок:

C++
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
struct recv_packet
{
    int magic;
    int code;
    int length;
    char *body;
 
};
 
char send_buff[1024+1] = "";
ZeroMemory(&send_buff, 1024);
memset(send_buff, 'A', 1024);
//send_buff[1024] = '\0';
recv_packet rcv_pkt = { 0 };
rcv_pkt.magic = MAGIC;
rcv_pkt.code = 0;
rcv_pkt.length = strlen(send_buff);
rcv_pkt.body = send_buff;
int size = sizeof(rcv_pkt.magic) + sizeof(rcv_pkt.code) + sizeof(rcv_pkt.length) + 1024+1;
 
 
if (send(ClientSocket, (char *)&rcv_pkt, size, 0) == SOCKET_ERROR)
{
    printf("Error %d\n", WSAGetLastError());
    closesocket(ClientSocket);
    WSACleanup();
    return 1;
}
Клиент на с# принимает данные вот так:

C#
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
public struct recv_packet
        {
            public int magic;
            public int code;
            public int length;
            public byte[] body;
 
        };
        public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            int port = 4000;
            TcpClient client = new TcpClient("127.0.0.1", 4000);
            NetworkStream nws = client.GetStream();
            BinaryWriter bw = new BinaryWriter(nws);
            BinaryReader br = new BinaryReader(nws);
            byte[] buff = new byte[512];
 
            send_packet pkt = new send_packet();
            pkt.magic = magic;
            pkt.cmd = (int)command.MOVE_MOUSE;
            while (true)
            {
 
                bw.Write(pkt.magic);
                bw.Write(pkt.cmd);
               
                //br.Read(buff, 0, 512);
                recv_packet rcv_pkt = new recv_packet();
                rcv_pkt.magic = br.ReadInt32();
                rcv_pkt.code = br.ReadInt32();
                rcv_pkt.length = br.ReadInt32();
                rcv_pkt.body = br.ReadBytes(rcv_pkt.length);
                //string str = rcv_pkt.length.ToString();
                string str = System.Text.Encoding.Default.GetString(rcv_pkt.body);
               
                MessageBox.Show(str);
               
                
            }
Не дело в том что в отладчике в rcv_pkt.body первыми идут какие-то другие байты, а не "65" как должно быть. Почему так происходит? На сервере в отладичке все тело ответа заполнено "А".
И вообще, может я не так данные принимаю и есть способ адекватнее?
Миниатюры
Прием данных клиентом TcpClient, данных попадается некорректные значения, почему?  
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
14.11.2015, 14:56
Ответы с готовыми решениями:

Сокеты. Прием данных клиентом от сервера
Здравствуйте. Задача такая: Клиент отправляет серверу данные, сервер, исходя из полученных данных, обращается к БД, результат запроса нужно...

Прием данных Winsock и преобразование данных Byte в String
VB.NET Здравствуйте! Вопрос! Есть обьект winsock для обмена сообщениями tcp\ip. http://vbbook.ru/1403703567/winsock-v-visual-basicnet/ ...

Найти минимальный элемент массива. Прием данных, как указатель на начало масива, и как копию данных
Дана задача. Задан масив чисел , без знака. Нужно написать групу процедур которые будут находить минимальный елемент массива. Должно быть...

19
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,569
14.11.2015, 23:15
А вы пробовали сачала прочитать полученные данные, а потом уже отправлять? А то вы сначала пишете в поток, а потом из него читаете, мне кажется это может вызвать проблемы как у вас.
0
7 / 7 / 2
Регистрация: 26.12.2011
Сообщений: 269
14.11.2015, 23:23  [ТС]
Спасибо за внимание к теме. Но суть в том что мне нужно сначала отправить данные потом получить. С основной проблемой я более-менее разобрался, теперь данные приходят от сервера нормально, но вот при посылке происходит что-то странное.
Вот часть, отвечающая за прием данных:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
struct send_packet
{
    int magic;
    int cmd;
};
 
iResult = recv(ClientSocket, buff, BUFLEN, 0);
if (iResult > 0)
{
    send_packet *pkt;
    pkt = (send_packet *)buff;
    printf("magc %d  cmd %d\n", pkt->magic, pkt->cmd);
    printf("Received %d %s\n", iResult, buff);
Я отсылаю на сервер структуру по-частям:
C#
1
2
bw.Write(pkt.magic);
bw.Write(pkt.cmd);
И сервер должен отобразить "magc 101 cmd 2". А у меня получается что сервер может отобразить "magc 2 cmd 0"
и "magc 0 cmd 2". Непонятно почему так происходит. Может дело в том что нельзя так последовательно отсылать данные через binarywriter? Но как тогда структуру отослать? Причем это касается в особенности структур с полем, которое содержит неизвестное заранее количество байт.
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,569
14.11.2015, 23:35
Данные не обязательно приходят целиком. Это нужно учитывать при получении. Нужно сначала долждаться получания всех данных, а потом уже их обрабатывать.

Вот у вас iResult может быть как 4, так и 8 байт, поэтому если вы ожидаете 8 байт, нужно принимать пока не будут получены все 8 байт, и только потом уже их как-то обрабатывать.
2
7 / 7 / 2
Регистрация: 26.12.2011
Сообщений: 269
14.11.2015, 23:40  [ТС]
Да, 8 байт это в примере, вообще я буду использовать структуру с полями переменной длинны, поэтому тут, наверное, на количество байт не положится. Но вот этот код
C#
1
2
bw.Write(pkt.magic);
bw.Write(pkt.cmd);
сразу шлет все данные или последовательно? Можно как-то сделать отправку единовременно или для этого нужен send() какой-нибудь?
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,569
15.11.2015, 00:04
Независимо от того как вы отправляете данные, они могут быть получены на другом конце частями. Поэтому это нужно учитывать и писать код который не сломается если данные пришли не полностью.
0
7 / 7 / 2
Регистрация: 26.12.2011
Сообщений: 269
15.11.2015, 00:05  [ТС]
Но если данные переменной длины?
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,569
15.11.2015, 00:12
Ну а как вы думаете что нужно сделать?
Hint: обычно в начале отправляют длинну данных.
0
7 / 7 / 2
Регистрация: 26.12.2011
Сообщений: 269
15.11.2015, 00:14  [ТС]
Но мне сначала нужно отправить идентификатор пакета (magic). А потом уже остальные данные. Мне кажется еще какой-то вариант должен быть, чтобы не отталкивается от результата recv(), не?
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,569
15.11.2015, 00:24
Цитата Сообщение от young_snake Посмотреть сообщение
Но мне сначала нужно отправить идентификатор пакета (magic)
Отправляйте. Он же у вас не переменного размера?
0
7 / 7 / 2
Регистрация: 26.12.2011
Сообщений: 269
15.11.2015, 10:12  [ТС]
Нет, тогда странно получается. Зачем нужны структуры данных если все равно по кусочку их отправлять придется.
0
 Аватар для pincet
1654 / 1153 / 173
Регистрация: 23.07.2010
Сообщений: 6,910
15.11.2015, 12:00
Цитата Сообщение от young_snake Посмотреть сообщение
Зачем нужны структуры данных если все равно по кусочку их отправлять придется.
отправляют целиком. Принимают частями, но протокол гарантирует доставку. Посему - маркер начала и конца сообщения (как правило STX и ETX)
http://www.theasciicode.com.ar... ode-2.html
0
7 / 7 / 2
Регистрация: 26.12.2011
Сообщений: 269
15.11.2015, 12:11  [ТС]
Так, тогда я запутался. Получается что нужно сначала отправить байт с STX, потом структуру, потом ETX. На принимающей стороне читать сокет, потом искать в приемном буфере ETX, и если его нет, то скидывать данные во временный буфер, потом читать еще, и делать так пока ETX не получу? Какая-то непростая схема получается.
0
 Аватар для pincet
1654 / 1153 / 173
Регистрация: 23.07.2010
Сообщений: 6,910
15.11.2015, 12:48
именно. Причем учитывая, что с ETX ты можешь получить еще и STX со своим ETX
0
7 / 7 / 2
Регистрация: 26.12.2011
Сообщений: 269
15.11.2015, 13:40  [ТС]
Как это, в каком случае такое может произойти? (И что тогда делать =\)
0
 Аватар для pincet
1654 / 1153 / 173
Регистрация: 23.07.2010
Сообщений: 6,910
15.11.2015, 13:54
разбирать цепочки, что делать. если ты отправил <STX>lfsdlkjfshlkfjgdfsk<ETX><STX>slkfjh slkfjhslkfhjsd<ETX>
протокол гарантирует доставку, но необязательно целиком, возможно частями
1
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,569
15.11.2015, 16:49
STX/ETX тут совсем не обязательны, можно просто указывать длинну.
0
7 / 7 / 2
Регистрация: 26.12.2011
Сообщений: 269
15.11.2015, 17:30  [ТС]
Я понял, наверное так и придется поступить. Потому что других адекватных путей пока не видно.
0
 Аватар для pincet
1654 / 1153 / 173
Регистрация: 23.07.2010
Сообщений: 6,910
16.11.2015, 09:09
Цитата Сообщение от Someone007 Посмотреть сообщение
STX/ETX тут совсем не обязательны, можно просто указывать длинну.
хе-хе. Где гарантия, что второй (третий,пятый) байт придут вместе с первым?
0
7 / 7 / 2
Регистрация: 26.12.2011
Сообщений: 269
16.11.2015, 12:43  [ТС]
Как и писал Someone007, придется ждать пока пакет целиком не прочитается, а потом уже смотреть че там пришло.

C++
1
2
3
4
5
6
7
8
9
10
ZeroMemory(&buff, BUFLEN);
int numRcvBytes = 0;
while (numRcvBytes < sizeof(send_packet))
{
    iResult = recv(ClientSocket, buff + numRcvBytes, BUFLEN, 0);
    numRcvBytes += iResult;
}
numRcvBytes = 0;
 
//работа с данными
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
16.11.2015, 12:43
Помогаю со студенческими работами здесь

Почему значения получаются одни и те же, при вводе разных данных?
Почему значения получаются одни и те же, при вводе разных данных? using System; using System.Collections.Generic; using...

Отправка различных данных через TcpServer/TcpClient
Мне надо сделать приложение, которое через tcp будет передавать несколько каналов данных:2 видео,2 звуковых и один текстовый. Как это можно...

Шифровка данных между клиентом и сервером
День добрый! (извините, коль кого обидел:)) Тема, может, и изъезженная, и всё же нужной информации найти не смог. Задача проста и...

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

Передача данных между клиентом и сервером
Какого мембера этот код не работает? Все же вроде верно написано! index.html: &lt;!DOCTYPE html&gt; &lt;html&gt; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru