Hi all i am Writing a prog. to receive the data from static IP and Port i have reached establishing connection to that IP and receiving the data but i am not getting complete data as i need please help in resolving the problem below is my code
TcpClient clientSocket = new TcpClient();
clientSocket.Connect("x.x.x.x", 1111);
if (clientSocket.Connected)
{
NetworkStream serverStream = clientSocket.GetStream();
while (true)
{
while (serverStream.DataAvailable)
{
// System.Threading.Thread.Sleep(5000);
byte[] inStream = new byte[1000768];
serverStream.Read(inStream, 0, (int)clientSocket.ReceiveBufferSize);
//serverStream.Read(inStream, 0, 1000768);
string returndata = System.Text.Encoding.ASCII.GetString(inStream);
if (true)// returndata.Substring(0, 1) == "$" && returndata.Substring(51, 1) == "~"
{
Invoke(new testDelegate(test), new object[] { returndata.Trim() });
}
}
}
}
my server sends
$01SSAA,25.64,414.47,12.164;~$02SSA,216.12,414.153,13.019;~
as response and i need to store it but i am not getting full response every time. i am getting it broken like only
- $01SSAA,,25.64,44 or 12.64;~$0SSAA,,
or
- $01SSAA,25.624,44.417,121.641;~$02SSAA,2116.121,414.5113
but when i use telnet and IP port i get full response
CodePudding user response:
If you take a look at ReadLine out of StreamReader:
// Reads a line. A line is defined as a sequence of characters followed by
// a carriage return ('\r'), a line feed ('\n'), or a carriage return
// immediately followed by a line feed. The resulting string does not
// contain the terminating carriage return and/or line feed. The returned
// value is null if the end of the input stream has been reached.
//
public override String ReadLine()
{
if (stream == null)
__Error.ReaderClosed();
#if FEATURE_ASYNC_IO
CheckAsyncTaskInProgress();
#endif
if (charPos == charLen)
{
if (ReadBuffer() == 0) return null;
}
StringBuilder sb = null;
do {
int i = charPos;
do {
char ch = charBuffer[i];
// Note the following common line feed chars:
// \n - UNIX \r\n - DOS \r - Mac
if (ch == '\r' || ch == '\n') {
String s;
if (sb != null) {
sb.Append(charBuffer, charPos, i - charPos);
s = sb.ToString();
}
else {
s = new String(charBuffer, charPos, i - charPos);
}
charPos = i 1;
if (ch == '\r' && (charPos < charLen || ReadBuffer() > 0)) {
if (charBuffer[charPos] == '\n') charPos ;
}
return s;
}
i ;
} while (i < charLen);
i = charLen - charPos;
if (sb == null) sb = new StringBuilder(i 80);
sb.Append(charBuffer, charPos, i);
} while (ReadBuffer() > 0);
return sb.ToString();
}
You can see it's getting into some quite involved stuff; it's basically reading all the data into a buffer elsewhere in the class, then chewing through that looking at chars until it encounters a \r
or an \n
. If it doesn't encounter one it loads everything it has so far into a StringBuilder and reads again, so that it can keep going until it gets one. In short the StringReader is buffering stuff itself so that it can spit lines out when it needs to (when asked)
There's no problem with you extending StreamReader to put your own logic in - clone this method and swap it so it's looking for ~
rather than \r
if (ch == '~') {
You also don't need the bit that checks if "the next char is \n, if it just found an \r"
//this if block can go
if (ch == '\r' && (charPos < charLen || ReadBuffer() > 0))
I havent given the full exact code you need (as in, "here; copy paste this and it'll work") because I'm not sure whether youre using netfw or netcore - the code above is from framework, but often the netcore classes differ a little; if you're inheriting some existing class to add functionality that is based on the existing code, it's easiest to make sure you're copying code out of the one you're using...
So the work I'm recommending you do is:
- Inherit streamreader
- Add a method (called ReadTilde?) that reads up to a
~
delimiter, based on Readline which reads up to an\r
delimiter - Add a constructor that is useful to you, and calls a base constructor (StreamReader has no 0 argument constructors so you need to add one that e.g. takes a stream, and calls the
base(stream)
) - Make a new instance of your streamreader, passing the network stream into it
- Call
ReadTilde()
repeatedly to get your data chopped on tildes
CodePudding user response:
I found the solution
try
{
byte[] inStream = new byte[1000768];
string ReturnData;
while (true)
{
using (TcpClient clientSocket = new TcpClient())
{
clientSocket.Connect(ConfigurationManager.AppSettings["TcpServerIP"], Convert.ToInt32(ConfigurationManager.AppSettings["Port"]));
if (clientSocket.Connected)
{
System.Threading.Thread.Sleep(5000);
using (NetworkStream NwServerStream = clientSocket.GetStream())
{
while (NwServerStream.DataAvailable)
{
NwServerStream.Read(inStream, 0, (int)clientSocket.ReceiveBufferSize);
//serverStream.Read(inStream, 0, 1000768);
ReturnData = System.Text.Encoding.ASCII.GetString(inStream);
if (true)//returndata.Substring(0, 1) == "$" && returndata.Substring(51, 1) == "~")
{
//Invoke(new testDelegate(SaveData), new object[] { ReturnData.Trim() });
SaveDataDB(ReturnData.Substring(ReturnData.IndexOf("$01RRA"), 24), ReturnData.Substring(ReturnData.IndexOf("$02RRA"), 24));
}
}
}
}
ReturnData = string.Empty;
Array.Clear(inStream, 0, inStream.Length);
GC.Collect();
}
}
}
catch (Exception ex)
{
throw;
}
finally {
GC.Collect();
}