Как прочитать все из сокета? C#
Релиб
Форумы       Участники    Календарь    Кто он-лайн?
Добро пожаловать, гость ( Вход | Регистрация )
        



Как прочитать все из сокета? C# Expand / Collapse
Автор
Сообщение
26.03.2003 17:16
новичок

новичокновичокновичокновичокновичокновичокновичокновичок

участник
Last Login: 18.04.2003 12:50
Сообщ.: 9, Visits: 100
Никто не подскажет, как прочитать полностью все данные из сокета?
Т.е. открываю сокет, что-то туда передаю и начинаю слушать его на ответ. Далее все полученные данные нужно куда-то сложить.

Но проблема в том, что заранее я не знаю, сколько там данных!
Если я пытаюсь читать их посредством Socket.Receive(byte[]), то сокет "поддвисает". Т.е. если я читаю достаточно большим массивом, то вычитав все из сокета до конца, но не заполнив до конца массив, я так и остаюсь в блокированном методе Receive. Но это происходит при повтороном прочтении. Может тут кто рабочим кодом поможет?
Если делать размер буфера в 1 байт, то все работает, но ждать приходится ужасно долго.

С networkStream точно такая же ерунда происходит. Только работает побыстрее :-)
Сообщ. #778033
26.03.2003 23:02
Forum Member

Forum MemberForum MemberForum MemberForum MemberForum MemberForum MemberForum MemberForum Member

участник
Last Login: 22.01.2006 15:13
Сообщ.: 37, Visits: 408
Тебе надо создать новый поток для сокета и тогда программа подвисать небудет. В MSDN кажется есть примеры работы с сокетами.
Сообщ. #778058
27.03.2003 9:33
новичок

новичокновичокновичокновичокновичокновичокновичокновичок

участник
Last Login: 18.04.2003 12:50
Сообщ.: 9, Visits: 100
Так в принципе так и сделано.

В общем задача такая - записывать в файл данные, которые передаются через сокет.
Сделал так - один поток GUI, где все отображается, один поток с TCPListener-ом, который пускается через TCPListener.Start(), как только устанавливается новое соединение на листенере, установленный сокет передается в новый поток, где и происходит собственно обработка. А именно, там из переданного сокета читается, все, что передано, затем открывается новый сокет (куда-то), в него записывается, то, что прочитано из первого-переданного сокета и читается оттуда результат, который в свою очередь передается опять же в первый сокет.
Т.е. другими словами, запустил прогу, направил браузер на 127.0.0.1:1000 (прога на нем слушает), получил страничку с www.relib.ru (в проге для второго сокета был именно этот адрес). И еще файлик, в котором записаны запросы браузера и ответы сервера. Все достаточно просто, но не работает нормально :-)
Уже сделал два варианта. Первый вариант, через Socket.Receive и второй через TCPClient-а.
Но и там и там возникли одинаковые трудности - либо не читается до конца, либо зависает, если буфер сделать больше одного байта.

Т.е. если я попытаюсь прочитать из сокета который подклбчается к удаленному серверу, буфер, который больше получаемых данных, то он читает, то, что есть и ждет, пока что-то еще не придет. Если сделать буфер меньше ожидаемых данных, то самый последний кусок не прочитывается (почему-не знаю). Если сделать буфер размером в 1 байт, то все прочитывается, но ужастно долго. Что не есть правильно. Насколько я понимаю, здесь проблема в том, что класс Soket, который вроде как является низлежащим классом для всех остальных, является враппером для WinSocks-а. И не может нивкакую определить размеры полученных данных (метод там есть, но он всегда возращает эксепшн).

И вторая проблема - немогу завершить поток с листенером, поскольку TCPListen.Start() блокирующий метод и поток на Abort ну совершенно никак не реагирует.

Сорцы, последний вариант с TCPClient-ом:

private Byte[] GetTCPResponce(Byte[] ByteGet)
{
NetworkStream networkStream = tcpClient.GetStream();
networkStream.Write(ByteGet, 0, ByteGet.Length);
MemoryStream ms=new MemoryStream();
String dataReceived ="";
while (networkStream.DataAvailable)
{
byte[] bytes = new byte[tcpClient.ReceiveBufferSize];
networkStream.Read(bytes, 0, (int) tcpClient.ReceiveBufferSize);
ms.Write(bytes,0,bytes.Length);
dataReceived=dataReceived+ System.Text.Encoding.ASCII.GetString(bytes);
}
LW.WriteString(oThread.Name,"Received (remote):"+dataReceived);
return ms.ToArray();
}

Здесь dataReceived это как раз строка, которая набирается для вывода в файл. LW это объект, который будет записывать в файл.
Сообщ. #778079
27.03.2003 9:36
новичок

новичокновичокновичокновичокновичокновичокновичокновичок

участник
Last Login: 18.04.2003 12:50
Сообщ.: 9, Visits: 100
Да, просьба учесть, что связь с веб сервером, чисто условная, программа должна работать не только с HTTP, поэтому использовать HTTPClient-а или чего-то похожего не получится.
Сообщ. #778080
27.03.2003 13:21
новичок

новичокновичокновичокновичокновичокновичокновичокновичок

участник
Last Login: 18.04.2003 12:50
Сообщ.: 9, Visits: 100
В общем, со второй проблемой, связанной с подвисанием потока с блокируещем листенером вроде как решилась. Сделал слушателя на основе событий, т.е. ловлю событие OnConnectRequest и в нем уже создаю другие потоки с сокетами. Теперь поток нормально закрывается по Abort.
Пытаюсь теперь сделать и чтение-запись с сокетами через события.
Сообщ. #778107
27.03.2003 14:18
новичок

новичокновичокновичокновичокновичокновичокновичокновичок

участник
Last Login: 18.04.2003 12:50
Сообщ.: 9, Visits: 100
В общем и первая проблема разрешилась при помощи событийной модели. Стало все и читаться полность и шустро работать и все такое.
Код который в общем-то и был нужен вот он:

int nBytesRec = rSocket.EndReceive(ar);
if( nBytesRec > 0 )
{
string sRecieved = System.Text.Encoding.ASCII.GetString(r_byBuff, 0, nBytesRec);
LW.WriteString(oThread.Name,sRecieved);
SendDataLocal(r_byBuff,nBytesRec);
AsyncCallback recieveData = new AsyncCallback(OnRecievedDataRemote);
rSocket.BeginReceive(r_byBuff, 0, r_byBuff.Length, SocketFlags.None, recieveData, rSocket);
}
Сообщ. #778114
« пред. тема | след. тема »


Эту тему читают Expand / Collapse
Посетители: 0 (0 гостей, 0 участников, 0 скрыт.участников)
Сейчас нет участников, просматривающих тему.
Модераторы: Alexey, boombastik, bazile, pl

Время GMT +3:00, Сейчас 12:19