|
|
|
новичок
      
участник
Last Login: 18.04.2003 12:50
Сообщ.: 9,
Visits: 100
|
|
Никто не подскажет, как прочитать полностью все данные из сокета? Т.е. открываю сокет, что-то туда передаю и начинаю слушать его на ответ. Далее все полученные данные нужно куда-то сложить.
Но проблема в том, что заранее я не знаю, сколько там данных! Если я пытаюсь читать их посредством Socket.Receive(byte[]), то сокет "поддвисает". Т.е. если я читаю достаточно большим массивом, то вычитав все из сокета до конца, но не заполнив до конца массив, я так и остаюсь в блокированном методе Receive. Но это происходит при повтороном прочтении. Может тут кто рабочим кодом поможет? Если делать размер буфера в 1 байт, то все работает, но ждать приходится ужасно долго.
С networkStream точно такая же ерунда происходит. Только работает побыстрее :-)
|
|
|
|
|
Forum Member
      
участник
Last Login: 22.01.2006 15:13
Сообщ.: 37,
Visits: 408
|
|
| Тебе надо создать новый поток для сокета и тогда программа подвисать небудет. В MSDN кажется есть примеры работы с сокетами.
|
|
|
|
|
новичок
      
участник
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 это объект, который будет записывать в файл.
|
|
|
|
|
новичок
      
участник
Last Login: 18.04.2003 12:50
Сообщ.: 9,
Visits: 100
|
|
| Да, просьба учесть, что связь с веб сервером, чисто условная, программа должна работать не только с HTTP, поэтому использовать HTTPClient-а или чего-то похожего не получится.
|
|
|
|
|
новичок
      
участник
Last Login: 18.04.2003 12:50
Сообщ.: 9,
Visits: 100
|
|
В общем, со второй проблемой, связанной с подвисанием потока с блокируещем листенером вроде как решилась. Сделал слушателя на основе событий, т.е. ловлю событие OnConnectRequest и в нем уже создаю другие потоки с сокетами. Теперь поток нормально закрывается по Abort. Пытаюсь теперь сделать и чтение-запись с сокетами через события.
|
|
|
|
|
новичок
      
участник
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); }
|
|
|
|