реализация из Delphi в C#
function T_Socket.RecvData: String;
var res: Integer;
var i: String
begin
iRecv := Recv(Sock, buff, sizeOf(buff), 0)
end;
Суть в том, что эта обработка принимает последовательно набор символов от клиента. И отправляет им ответ в зависимости от условия, предоставленного ниже.
У меня есть сервер, такого типа:
listener.Start();
while(true)
{
using (TcpClient c = listener.AcceptTcpClient())
using (NetworkStream n = c.GetStream())
{
MessageBox.Show("connected");
char msg = new BinaryReader(n).ReadChar();
strmsg = Convert.ToString(msg);
MessageBox.Show(strmsg);
for (i = 0; i < data.Count(); i++)
if (data == strmsg)
{
int k = i + 2;
strmsg = data[k] + data[k + 1];
BinaryWriter w = new BinaryWriter(n);
msg = Convert.ToChar(w);
w.Write(msg);
w.Flush();
}
}
}
listener.Stop();
Что то я подзапарился над конвертацией в форматы, то что выше (BinaryReader(n).ReadChar()) читает во первых только один символ, а во вторых вылетает при попытке писать char в порт клиента(w.Write(msg)).
data - набор данных типа List<string>
// однобайтовая кириллическая
TcpListener listener = new TcpListener(IPAddress.Any, 9101);
listener.Start();
while(true) {
using (TcpClient client = listener.AcceptTcpClient())
using (NetworkStream stream = client.GetStream())
using (StreamReader reader = new StreamReader(stream, encoding))
using (StreamWriter writer = new StreamWriter(stream, encoding)) {
MessageBox.Show("connected");
// сколько данных читать?
string input = reader.ReadLine(); // читает строку до следующего Environment.NewLine
// и пропускает его
// пример записи List<string> data в сетевой поток
foreach(string line in data) {
if(input == line) {
writer.WriteLine("You selected: " + input);
} else {
// writer.Write(line); // без Environment.NewLine
writer.WriteLine(line); // добавляет Environment.NewLine
}
}
writer.Flush(); // сбрасываем данные из внутреннего буфера StreamWriter
// в сетевой поток
// <-- тут соединение разорвется
}
}
listener.Stop();
string input = reader.ReadLine(); // читает строку до следующего Environment.NewLine
// и пропускает его
В том то вся и проблема, что неизвестно сколько данных читать.
И я не могу даже понять, считывает он что то или нет :(
В случае с BinaryReader.ReadChar считывает только первый символ, но покрайней мере, хоть что то считывает
Про StreamReader прочитал такую вещь.
Класс StreamReader может выйти из под контроля при работе с потоком NetworkStream, даже если вы собираетесь вызывать только ReadLine. Причина в том, что у класса StreamReader имеется буфер предварительного чтения, и дело может закончится попыткой прочитать больше байтов, чем доступно в настоящий момент и приостановкой работы на неопределенное время.
По этой причине, я не рискнул создавать таким образом.
Может есть какое нибудь другое решение?
PS: И еще. Только что обнаружил. Первое сообщение доходит только тогда, когда поступает второе. Причем после этого, происходит отключение клиента. Что то я недопонимаю...
Про StreamReader прочитал такую вещь.
Все это говорит лишь о том, что лучше воздержаться от использования ReadLine в production-коде.
По этой причине, я не рискнул создавать таким образом.
Вводится собственный контроль длины считываемой строки ;)
Для начала я предложу вам разобраться с протоколом, на котором вы хотите организовать взаимодействие:
В том то вся и проблема, что неизвестно сколько данных читать.
Вот и займитесь этим вопросом. Не зная что за данные вам приходят вы не сможете с ними работать.
В сети данные ходят пакетами, отталкивайтесь от этого.
Для отладки сетевых приложений есть как мощные снифферы вроде WireShark или MS NetworkMonitor, так и элементарнейшая утиллита командной строки telnet (попробуйте ее).
Для начала я предложу вам разобраться с протоколом, на котором вы хотите организовать взаимодействие:
Вот и займитесь этим вопросом. Не зная что за данные вам приходят вы не сможете с ними работать.
В сети данные ходят пакетами, отталкивайтесь от этого.
Каким образом выполнить контроль? Я знаю, что ко мне, т.е. к серверу приходят сообщения типа:
46064226
2000131467848
20 589
но они разной длинны, и возможности сделать их одинаковыми нет.
Взаимодействие по протоколу tcp/ip, клиента я к сожалению конфигурировать не могу.
Но даже если в сети и ходят данные пакетами, как все таки сделать так, чтоб клиент не отключался после отправки сообщения?
И все таки, почему первое сообщение приходит после отправки второго?
к серверу приходят сообщения типа:
46064226
2000131467848
20 589
то сможете ответить на вопрос
Взаимодействие по протоколу tcp/ip, клиента я к сожалению конфигурировать не могу.
TCP/IP - это транспортный протокол, я же спрашиваю про протокол прикладного уровня, т.е. соглашения о передаче данных между программами. Простой аналог: HTTP - это текстовый (ну, не совсем, конечно) протокол прикладного уровня.
Клиент отключается сам?
Я уже в третий раз спрашиваю, как обмен данных происходит, пока вы не поймете этого, вы не сможете написать программу.
Наводящие вопросы:
к серверу приходят сообщения типа:
46064226
2000131467848
20 589
1) Какой они максимальной длины?
2) Если это текстовый протокол, то какая используется кодировка (ANSI, UTF-8, и т.д.)?
3) Сколько сообщений отправляет клиент?
4) Что нужно отвечать (если нужно) клиенту на каждое сообщение?
Сообщения приходят посимвольно от устройства:
2000131467848 - это приходящие последовательно символы, т.е. 13 байт (точно измерить не могу сейчас)
Все сообщения разной длины, но чтоб удостоверится, отпишусь завтра, надо глянуть будет.
Клиентом является устройство, которое может быть TCP клиентом. На прикладном уровне я не скажу.
Клиент отправляет одно сообщение, с набором этих символов.
Я тут подумал, что можно сделать так
using (NetworkStream n = c.GetStream())
{
MessageBox.Show("connected");
char[] msg = new BinaryReader(n).ReadChars(256);
string chartomsg = new string(msg);
for (i = 0; i < data.Count(); i++)
if (data == chartomsg)
{
int k = i + 2;
strmsg = data[k] + data[k + 1];
BinaryWriter w = new BinaryWriter(n);
char[] msgtochar = strmsg.ToCharArray();
w.Write(msgtochar);
w.Flush();
}
}
}
listener.Stop();
Я постараюсь упростить объяснение кодом. Очень признателен вам, за отклик.
В общем, я приложу файл, в котором написан данный сервер для этого устройства на C, полностью рабочий. А вот как реализовать его в C#?.... Не думаю, что слишком отличается от Windows кода, разве что библиотеками.