In C# to test if UltraVNC was up and running on a local machine I would do this
public static bool TestAvailablility(int port, string responseStartsWith)
{
bool toReturn = false;
try
{
using (TcpClient client1 = new TcpClient())
{
client1.ReceiveTimeout = 10000;
client1.SendTimeout = 10000;
client1.Connect("localhost", port);
using (NetworkStream stream = client1.GetStream())
{
Byte[] response = new Byte[4096];
Int32 bytes = 0;
string serverReturnString = null;
bytes = stream.Read(response, 0, response.Length);
serverReturnString = System.Text.Encoding.ASCII.GetString(response, 0, bytes);
Console.WriteLine("TestAvailablility: serverReturnString = {0}", serverReturnString);
if (serverReturnString.StartsWith(responseStartsWith, StringComparison.OrdinalIgnoreCase))
{
toReturn = true;
}
}
}
}
catch (Exception ex) // SocketException for connect, IOException for the read.
{
Console.WriteLine("TestAvailable - Could not connect to VNC server. Exception info: ", ex);
}
return toReturn;
}
I'm new to Java so I'm hoping someone can help me with an equivalent method to preform this action.
Here's what I came up with:
FYI using Autocomplete in Eclipse + Java API you can translate C# to Java pretty easily.
public static boolean testAvailablility(int port, String responseStartsWith) {
boolean toReturn = false;
try {
Socket client1 = new Socket();
client1.setSoTimeout(10000);
client1.bind(new InetSocketAddress("localhost", port));
InputStream stream = client1.getInputStream();
byte[] response = new byte[4096];
int bytes = 0;
String serverReturnString = null;
bytes = stream.read(response, 0, response.length);
serverReturnString = String.valueOf(bytes);
System.out.println("TestAvailablility: serverReturnString = {0} " + serverReturnString);
if (serverReturnString.toLowerCase().startsWith(responseStartsWith.toLowerCase()))
toReturn = true;
} catch (Exception ex) // SocketException for connect, IOException for
// the read.
{
System.out.println("TestAvailable - Could not connect to VNC server. Exception info: ");
ex.printStackTrace();
}
return toReturn;
}
Related
I have a serious issue with my .NET server application. In production, the application will reach 100% CPU usage and get stuck there until I restart the server. It seems completely random. Sometimes it will happen 10 minutes after I start the server. Sometimes a week after I start the server. There are no logs that indicate what causes it either. But I am guessing I wrote the TCP client/server wrong and there is some edge case that can cause this. I believe this issue didn't start happening until I added this TCP client/server. I say client and server because this class does both and I actually have two different server applications that use it to communicate to each other and they both experience this issue randomly (not at the same time). Also side note user clients from all over the world use this same TCP client/server class: Bridge to connect to the server as well.
Is there anything I can do to try and figure out what's causing this? It's a .NET console app running on a Linux VM on Google Cloud Platform.
If you are knowledgable with .NET TCP classes then perhaps you can find an issue with this code?
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace SBCommon
{
public class Bridge<T> where T : struct, IConvertible
{
public Dictionary<int, BridgeHandler> bridgeHandlers;
public ClientHandler clientHandler;
TcpListener server = null;
public Bridge(int port, Dictionary<int, BridgeHandler> bridgeHandlers)
{
server = new TcpListener(IPAddress.Any, port);
server.Start();
this.bridgeHandlers = bridgeHandlers;
Logging.Info($"bridge listener on address {IPAddress.Any} port {port}");
}
public void StartListener()
{
try
{
Logging.Info($"Starting to listen for TCP connections");
while (true)
{
Logging.Debug("TCP client ready");
TcpClient client = server.AcceptTcpClient();
Logging.Debug("TCP client connected");
Thread t = new Thread(new ParameterizedThreadStart(HandleConnection));
t.Start(client);
}
}
catch (SocketException e)
{
Logging.Error($"SocketException: {e}");
server.Stop();
}
}
public void HandleConnection(object obj)
{
TcpClient client = (TcpClient)obj;
client.ReceiveTimeout = 10000; // adding this to see if it fixes the server crashes
var stream = client.GetStream();
try
{
if (stream.CanRead)
{
byte[] messageLengthBytes = new byte[4];
int v = stream.Read(messageLengthBytes, 0, 4);
if (v != 4)
{
// this is happening and then the server runs at over 100% so adding lots of logging to figure out what's happening
StringBuilder sb = new StringBuilder($"could not read incoming message. Read {v} bytes");
try
{
sb.Append($"\nfrom {(IPEndPoint)client.Client.RemoteEndPoint}");
}
catch (Exception e)
{
sb.Append($"\ncould not get client's IP address because {e}");
}
sb.Append($"\nclient.Available: {client.Available}");
sb.Append($"\nclient.SendBufferSize: {client.SendBufferSize}");
Logging.Error(sb.ToString());
stream.Close();
client.Close();
stream.Dispose();
client.Dispose();
return;
}
int messageLength = BitConverter.ToInt32(messageLengthBytes, 0);
int readPos = 0;
byte[] recievedData = new byte[messageLength];
while (readPos < messageLength)
{
int size = Math.Min(messageLength - readPos, client.ReceiveBufferSize);
v = stream.Read(recievedData, readPos, size);
readPos += v;
}
Bits incoming = new Bits(recievedData);
incoming.InitReadableBuffer();
int packetType = incoming.ReadInt();
Bits outgoing;
if (packetType == int.MaxValue)
{
Logging.Info($"recieved client handler message");
outgoing = clientHandler(incoming, client);
}
else
{
if (bridgeHandlers.ContainsKey(packetType))
{
Logging.Info($"recieved {(T)(object)packetType}");
outgoing = bridgeHandlers[packetType](incoming);
}
else
{
Logging.Error($"recieved unhandled packetType {packetType}!!!!!");
return;
}
}
if (outgoing != null)
{
#region send response
byte[] sendData = new byte[outgoing.Length() + 4];
// first write the length of the message
BitConverter.GetBytes(outgoing.Length()).CopyTo(sendData, 0);
// then write the message
outgoing.ToArray().CopyTo(sendData, 4);
stream.Write(sendData, 0, sendData.Length);
outgoing.Dispose();
#endregion
}
else
{
byte[] sendData = new byte[4];
BitConverter.GetBytes(0).CopyTo(sendData, 0);
stream.Write(sendData, 0, sendData.Length);
}
}
else
{
Logging.Info("Sorry. You cannot read from this NetworkStream.");
}
}
catch (Exception e)
{
Logging.Error($"Exception: {e}");
stream.Close();
client.Close();
stream.Dispose();
client.Dispose();
}
}
public static void SendTCPmessageFireAndForget(IPEndPoint iPEndPoint, Bits bits)
{
Task.Run(() =>
{
SendTCPmessage(iPEndPoint, bits, out _);
bits.Dispose();
});
}
public static async Task<Bits> SendTCPmessageAsync(IPEndPoint iPEndPoint, Bits bits)
{
TcpClient client = new TcpClient();
client.Connect(iPEndPoint);
NetworkStream stream = client.GetStream();
stream.WriteTimeout = 5000;
stream.ReadTimeout = 5000;
// Send the message
byte[] bytes = new byte[bits.Length() + 4];
BitConverter.GetBytes(bits.Length()).CopyTo(bytes, 0); // write length of message
bits.ToArray().CopyTo(bytes, 4);
await stream.WriteAsync(bytes, 0, bytes.Length);
// Read the response
byte[] messageLengthBytes = new byte[4];
int v = await stream.ReadAsync(messageLengthBytes, 0, 4);
if (v != 4) throw new Exception("could not read incoming message");
int messageLength = BitConverter.ToInt32(messageLengthBytes, 0);
if (messageLength > 0)
{
int readPos = 0;
byte[] recievedData = new byte[messageLength];
while (readPos < messageLength)
{
int size = Math.Min(messageLength - readPos, client.ReceiveBufferSize);
v = await stream.ReadAsync(recievedData, readPos, size);
readPos += v;
}
stream.Close();
client.Close();
bits = new Bits(recievedData);
}
else bits = null;
return bits;
}
public static void SendTCPmessage(IPEndPoint iPEndPoint, Bits bits, out Bits responseBits)
{
try
{
TcpClient client = new TcpClient();
client.Connect(iPEndPoint);
NetworkStream stream = client.GetStream();
stream.WriteTimeout = 50000;
stream.ReadTimeout = 50000;
// Send the message
byte[] bytes = new byte[bits.Length() + 4];
BitConverter.GetBytes(bits.Length()).CopyTo(bytes, 0); // write length of message
bits.ToArray().CopyTo(bytes, 4);
stream.Write(bytes, 0, bytes.Length);
// Read the response
byte[] messageLengthBytes = new byte[4];
if (stream.Read(messageLengthBytes, 0, 4) != 4) throw new Exception("could not read incoming message");
int messageLength = BitConverter.ToInt32(messageLengthBytes, 0);
if (messageLength > 0)
{
int readPos = 0;
byte[] recievedData = new byte[messageLength];
while (readPos < messageLength)
{
int size = Math.Min(messageLength - readPos, client.ReceiveBufferSize);
int v = stream.Read(recievedData, readPos, size);
readPos += v;
}
stream.Close();
client.Close();
responseBits = new Bits(recievedData);
}
else responseBits = null;
}
catch (Exception e)
{
Logging.Error($"Exception: {e}");
responseBits = null;
}
}
}
public delegate Bits BridgeHandler(Bits incoming);
public delegate Bits ClientHandler(Bits incoming, TcpClient client);
}
Notes:
Bits is a class I use for serialization.
You can see in StartListener that I start a thread for every incoming connection
I also use while (true) and AcceptTcpClient to accept tcp connections. But maybe I shouldn't be doing it that way?
I read the first 4 bytes as an int from every packet to determine what kind of packet it is.
then I continue to to read the rest of the bytes until I have read all of it.
There is a lot wrong with your existing code, so it's hard to know what exactly is causing the issue.
Mix of async and non-async calls. Convert the whole thing to async and only use those, do not do sync-over-async.
Assuming stream.Read is actually returning the whole value in one call.
Lack of using in many places.
Repetitive code which should be refactored into functions.
Unsure what the use of bits.ToArray is and how efficient it is.
You may want to add CancellationToken to be able to cancel the operations.
Your code should look something like this:
public class Bridge<T> : IDisposable where T : struct, IConvertible
{
public Dictionary<int, BridgeHandler> bridgeHandlers;
public ClientHandler clientHandler;
TcpListener server;
public Bridge(int port, Dictionary<int, BridgeHandler> bridgeHandlers)
{
server = new TcpListener(IPAddress.Any, port);
this.bridgeHandlers = bridgeHandlers;
Logging.Info($"bridge listener on address {IPAddress.Any} port {port}");
}
public async Task StartListener()
{
try
{
Logging.Info($"Starting to listen for TCP connections");
server.Start();
while (true)
{
Logging.Debug("TCP client ready");
TcpClient client = await server.AcceptTcpClientAsync();
Logging.Debug("TCP client connected");
Task.Run(async () => await HandleConnection(client));
}
}
catch (SocketException e)
{
Logging.Error($"SocketException: {e}");
}
finally
{
if (listener.Active)
server.Stop();
}
}
public async Task HandleConnection(TcpClient client)
{
using client;
client.ReceiveTimeout = 10000; // adding this to see if it fixes the server crashes
using var stream = client.GetStream();
try
{
var incoming = await ReadMessageAsync(stream);
incoming.InitReadableBuffer();
int packetType = incoming.ReadInt();
Bits outgoing;
if (packetType == int.MaxValue)
{
Logging.Info($"recieved client handler message");
outgoing = clientHandler(incoming, client);
}
else
{
if (bridgeHandlers.TryGetValue(packetType, handler))
{
Logging.Info($"recieved {(T)(object)packetType}");
outgoing = handler(incoming);
}
else
{
Logging.Error($"recieved unhandled packetType {packetType}!!!!!");
return;
}
}
using (outgoing);
await SendMessageAsync(stream, outgoing);
}
catch (Exception e)
{
Logging.Error($"Exception: {e}");
}
}
public static void SendTCPmessageFireAndForget(IPEndPoint iPEndPoint, Bits bits)
{
Task.Run(async () =>
{
using (bits)
await SendTCPmessageAsync(iPEndPoint, bits);
});
}
public static async Task<Bits> SendTCPmessageAsync(IPEndPoint iPEndPoint, Bits bits)
{
using TcpClient client = new TcpClient();
await client.ConnectAsync(iPEndPoint);
using NetworkStream stream = client.GetStream();
stream.WriteTimeout = 5000;
stream.ReadTimeout = 5000;
await SendMessageAsync(stream, bits);
return await ReadMessageAsync(stream);
}
}
private async Task SendMessageAsync(Stream stream, Bits message)
{
var lengthArray = message == null ? new byte[4] : BitConverter.GetBytes(bits.Length());
await stream.WriteAsync(lengthArray, 0, lengthArray.Length); // write length of message
if (message == null)
return;
var bytes = bits.ToArray();
await stream.WriteAsync(bytes, 0, bytes.Length);
}
private async Task<Bits> ReadMessageAsync(Stream stream)
{
var lengthArray = new byte[4];
await FillBuffer(stream, lengthArray);
int messageLength = BitConverter.ToInt32(lengthArray, 0);
if (messageLength == 0)
return null;
byte[] receivedData = new byte[messageLength];
await FillBuffer(stream, receivedData);
bits = new Bits(receivedData);
return bits;
}
private async Task FillBuffer(Stream stream, byte[] buffer)
{
int totalRead = 0;
int bytesRead = 0;
while (totalRead < buffer.Length)
{
var bytesRead = await stream.ReadAsync(lengthArray, totalRead, buffer.Length - totalRead);
totalRead += bytesRead;
if(bytesRead <= 0)
throw new Exception("Unexpected end of stream");
}
}
I am using a c# application that sends data to my server.
I want to send bytes along with the data so that I can handle at server code if the data size is large it can break there only.
I am not getting how to send bytes value along with the data.
The below is my client side sending part and my server side responding part to client.
Client Code :-
public bool sendData(StringBuilder QueryVal)
{
TcpClient clientSocket = new System.Net.Sockets.TcpClient();
try
{
clientSocket.Client.Connect(Serverip, 8888);
var connect = clientSocket.Connected;// it can be ? clientSocket.Client.Connected
if (connect == true)
{
try
{
NetworkStream serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(QueryVal + "$");
serverStream.Write(outStream, 0, outStream.Length);
String decodedString = System.Text.Encoding.ASCII.GetString(outStream);
decodedData(decodedString.ToString());
serverStream.Flush();
byte[] inStream = new byte[clientSocket.ReceiveBufferSize];
serverStream.Read(inStream, 0, (int)clientSocket.ReceiveBufferSize);
string returndata = System.Text.Encoding.ASCII.GetString(inStream);
//MessageBox.Show("Receive data is: " + returndata);
int SendByte = outStream.Count();
int ReceivedByte = Convert.ToInt32(returndata);
try
{
clientSocket.Client.Shutdown(SocketShutdown.Both);
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
bool chk = clientSocket.Connected;// this line should be comment
if (SendByte == ReceivedByte) { return true; }
else { return false; }
}
catch (Exception ex)
{
StackFrame objtrack = new StackFrame();
var methodinfo = objtrack.GetMethod();
string calssName = methodinfo.DeclaringType.Name;
string methoname = methodinfo.Name;
string Lineno = Convert.ToString(ex.LineNumber());
log(ex.Message, calssName, methoname, Lineno);
return false;
}
}
else
{
return false;
}
}
catch (Exception ex)
{
StackFrame objtrack = new StackFrame();
var methodinfo = objtrack.GetMethod();
string calssName = methodinfo.DeclaringType.Name;
string methoname = methodinfo.Name;
string Lineno = Convert.ToString(ex.LineNumber());
log(ex.Message, calssName, methoname, Lineno);
return false;
}
}
Server Code :-
Byte[] sendBytesAA = Encoding.ASCII.GetBytes(ReceiveSize.ToString());
ReceiveSize = 0;
networkStream.Write(sendBytesAA, 0, sendBytesAA.Length);
Don't convert data to string in can mess up the data and adds unnecessary processing time. Try following code :
TcpClient clientSocket = new TcpClient();
NetworkStream serverStream = clientSocket.GetStream();
List<byte> inStream = new List<byte>();
serverStream.Read(inStream.ToArray(), 0, (int)clientSocket.ReceiveBufferSize);
long length = inStream.Count;
byte[] byteLength = BitConverter.GetBytes(length);
inStream.InsertRange(0, byteLength.ToList());
I have a stream coming in that varies in length but has a start and stop character. When I run this code:
public TCPListener()
{
Int32 port = 31001;
IPAddress localAddr = IPAddress.Parse("192.168.0.78"); //Local
server = new TcpListener(localAddr, port);
server.Start();
while (true)
{
// Console.Write("Waiting for a connection...-- ");
TcpClient client = server.AcceptTcpClient();
// Console.WriteLine("new client connected");
try
{
ThreadPool.QueueUserWorkItem(new WaitCallback(HandleClient), client);
}
catch (Exception ex)
{ }
}
}
private void HandleClient(object tcpClient)
{
// string path = #"c:\Test.txt";
TcpClient client = (TcpClient)tcpClient;
Byte[] bytes = new Byte[135];
String data = null;
int i;
try
{
NetworkStream stream = client.GetStream();
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
URLObject oU = new URLObject();
oU = oDecode.TextFrameDecode(data);
Console.WriteLine(data);
Console.WriteLine("");
}
}
catch (Exception ex)
{ }
// Console.WriteLine(data);
}
I get a lot of data every second; I get the data, but it's broken up sometimes into chunks that are not parsable. When I run this code to look for the end delimiter, the feed only get one connection every couple of minutes with only one record so I think the data is getting truncated which is not correct.
static void Main(string[] args)
{
Int32 port = 31001;
IPAddress localAddr = IPAddress.Parse("192.168.0.78"); //Local
server = new TcpListener(localAddr, port);
server.Start();
while (true)
{
Console.Write("Waiting for a connection...-- ");
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("new client connected");
try
{
ThreadPool.QueueUserWorkItem(new WaitCallback(HandleClient), client);
}
catch (Exception ex)
{ }
}
}
static void HandleClient(object tcpClient)
{
TcpClient client = (TcpClient)tcpClient;
Byte[] bytes = new Byte[135];
String data = null;
int i;
try
{
using (NetworkStream stream = client.GetStream())
using (StreamReader reader = new StreamReader(stream))
{
string inputLine = reader.ReadLineSingleBreak();
inputLine = inputLine + "#";
Console.WriteLine(inputLine);
URLObject oU = new URLObject();
oU = oDecode.TextFrameDecode(inputLine);
}
}
catch (Exception ex)
{ }
}
}
public static class StreamReaderExtensions
{
public static string ReadLineSingleBreak(this StreamReader self)
{
StringBuilder currentLine = new StringBuilder();
int i;
char c;
while ((i = self.Read()) >= 0)
{
c = (char)i;
if (c == '#')
{
break;
}
currentLine.Append(c);
}
return currentLine.ToString();
}
}
I need a mix of both... get all the data but then parse it correctly.
I did fix it by Pieter Witvoet advice:
static private TcpListener server = null;
static private Decode oDecode = new Decode();
static private string sLeftOver = string.Empty;
static void Main(string[] args)
{
Int32 port = 31001;
IPAddress localAddr = IPAddress.Parse("192.168.0.78"); //Local
server = new TcpListener(localAddr, port);
server.Start();
while (true)
{
Console.Write("Waiting for a connection...-- ");
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("new client connected");
try
{
ThreadPool.QueueUserWorkItem(new WaitCallback(HandleClient), client);
}
catch (Exception ex)
{ }
}
}
static void HandleClient(object tcpClient)
{
TcpClient client = (TcpClient)tcpClient;
Byte[] bytes = new Byte[256];
String data = null;
int i;
try
{
NetworkStream stream = client.GetStream();
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
URLObject oU = new URLObject();
Console.WriteLine(data);
Console.WriteLine("");
//Split data here
string[] aData = Regex.Split(data, #"(?<=[#])");
foreach (string s in aData)
{
string sData = s;
sData = sLeftOver + sData;
if (sData.EndsWith("#"))
{
sLeftOver = string.Empty;
Console.WriteLine(sData);
Console.WriteLine("");
oU = oDecode.TextFrameDecode(sData);
}
else
{
sLeftOver = s;
}
}
}
}
catch (Exception ex)
{ }
}
I'm trying to make a server client using a local console server on my pc and a client on windows phone 8.1. The problem that I have is that I don't know how to read the incoming data from the client. I've searched the internet and read serveral microsoft tutorials but they do not explain how to read the incoming data in the server. Here's what I have.
Client on windows phone 8.1:
private async void tryConnect()
{
if (connected)
{
StatusLabel.Text = "Already connected";
return;
}
try
{
// serverHostnameString = "127.0.0.1"
// serverPort = "1330"
StatusLabel.Text = "Trying to connect ...";
serverHost = new HostName(serverHostnameString);
// Try to connect to the
await clientSocket.ConnectAsync(serverHost, serverPort);
connected = true;
StatusLabel.Text = "Connection established" + Environment.NewLine;
}
catch (Exception exception)
{
// If this is an unknown status,
// it means that the error is fatal and retry will likely fail.
if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
{
throw;
}
StatusLabel.Text = "Connect failed with error: " + exception.Message;
// Could retry the connection, but for this simple example
// just close the socket.
closing = true;
// the Close method is mapped to the C# Dispose
clientSocket.Dispose();
clientSocket = null;
}
}
private async void sendData(string data)
{
if (!connected)
{
StatusLabel.Text = "Must be connected to send!";
return;
}
UInt32 len = 0; // Gets the UTF-8 string length.
try
{
StatusLabel.Text = "Trying to send data ...";
// add a newline to the text to send
string sendData = "jo";
DataWriter writer = new DataWriter(clientSocket.OutputStream);
len = writer.MeasureString(sendData); // Gets the UTF-8 string length.
// Call StoreAsync method to store the data to a backing stream
await writer.StoreAsync();
StatusLabel.Text = "Data was sent" + Environment.NewLine;
// detach the stream and close it
writer.DetachStream();
writer.Dispose();
}
catch (Exception exception)
{
// If this is an unknown status,
// it means that the error is fatal and retry will likely fail.
if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
{
throw;
}
StatusLabel.Text = "Send data or receive failed with error: " + exception.Message;
// Could retry the connection, but for this simple example
// just close the socket.
closing = true;
clientSocket.Dispose();
clientSocket = null;
connected = false;
}
}
(from http://msdn.microsoft.com/en-us/library/windows/apps/xaml/jj150599.aspx)
And the server:
public class Server
{
private TcpClient incomingClient;
public Server()
{
TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 1330);
listener.Start();
Console.WriteLine("Waiting for connection...");
while (true)
{
//AcceptTcpClient waits for a connection from the client
incomingClient = listener.AcceptTcpClient();
//start a new thread to handle this connection so we can go back to waiting for another client
Thread thread = new Thread(HandleClientThread);
thread.IsBackground = true;
thread.Start(incomingClient);
}
}
private void HandleClientThread(object obj)
{
TcpClient client = obj as TcpClient;
Console.WriteLine("Connection found!");
while (true)
{
//how to read and send data back?
}
}
}
It comes to the point where the server prints 'Connection found!', but I don't know how to go further.
Any help is appreciated!
EDIT:
Now my handleclientthread method looks like this:
private void HandleClientThread(object obj)
{
TcpClient client = obj as TcpClient;
netStream = client.GetStream();
byte[] rcvBuffer = new byte[500]; // Receive buffer
int bytesRcvd; // Received byte count
int totalBytesEchoed = 0;
Console.WriteLine("Connection found!");
while (true)
{
while ((bytesRcvd = netStream.Read(rcvBuffer, 0, rcvBuffer.Length)) > 0)
{
netStream.Write(rcvBuffer, 0, bytesRcvd);
totalBytesEchoed += bytesRcvd;
}
Console.WriteLine(totalBytesEchoed);
}
}
But it still doesn't write the bytes to the console
So... after a lot of searching the internet I have found a solution...
Server: to read from the server and send data back to the phone:
// method in a new thread, for each connection
private void HandleClientThread(object obj)
{
TcpClient client = obj as TcpClient;
netStream = client.GetStream();
Console.WriteLine("Connection found!");
while (true)
{
// read data
byte[] buffer = new byte[1024];
int totalRead = 0;
do
{
int read = client.GetStream().Read(buffer, totalRead, buffer.Length - totalRead);
totalRead += read;
} while (client.GetStream().DataAvailable);
string received = Encoding.ASCII.GetString(buffer, 0, totalRead);
Console.WriteLine("\nResponse from client: {0}", received);
// do some actions
byte[] bytes = Encoding.ASCII.GetBytes(received);
// send data back
client.GetStream().WriteAsync(bytes, 0, bytes.Length);
}
}
Phone(client): to send messages from the phone and read the messages from server:
private async void sendData(string dataToSend)
// import for AsBuffer(): using System.Runtime.InteropServices.WindowsRuntime;
{
if (!connected)
{
StatusLabel.Text = "Status: Must be connected to send!";
return;
}
try
{
byte[] data = GetBytes(dataToSend);
IBuffer buffer = data.AsBuffer();
StatusLabel.Text = "Status: Trying to send data ...";
await clientSocket.OutputStream.WriteAsync(buffer);
StatusLabel.Text = "Status: Data was sent" + Environment.NewLine;
}
catch (Exception exception)
{
if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
{
throw;
}
StatusLabel.Text = "Status: Send data or receive failed with error: " + exception.Message;
closing = true;
clientSocket.Dispose();
clientSocket = null;
connected = false;
}
readData();
}
private async void readData()
{
StatusLabel.Text = "Trying to receive data ...";
try
{
IBuffer buffer = new byte[1024].AsBuffer();
await clientSocket.InputStream.ReadAsync(buffer, buffer.Capacity, InputStreamOptions.Partial);
byte[] result = buffer.ToArray();
StatusLabel.Text = GetString(result);
}
catch (Exception exception)
{
if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
{
throw;
}
StatusLabel.Text = "Receive failed with error: " + exception.Message;
closing = true;
clientSocket.Dispose();
clientSocket = null;
connected = false;
}
}
The 'await clientSocket.InputStream.ReadAsync(buffer, buffer.Capacity, InputStreamOptions.Partial)' command in the readData method was very unclear for me. I didn't know you had to make a new buffer, and the ReadAsync-method fills it(as i inderstand it). Found it here: StreamSocket.InputStreamOptions.ReadAsync hangs when using Wait()
I'm writing client-server application. Client sending command and server recieves it and do some manipulations. It works well. But when i'm trying to send response from server to client and recieve it on client side nothing happens. Even server do nothing. Program hangs and only Shift+F5 helps to finish it.
Server code:
class TNPClient
{
TNPBaseInterraction tnp_base;
private void SendError(TcpClient Client, int Code)
{
byte[] buf = Encoding.ASCII.GetBytes(Code.ToString());
Client.GetStream().Write(buf, 0, buf.Length);
Client.Close();
}
private void SendResponse(TcpClient Client, string response)
{
byte[] buf = Encoding.ASCII.GetBytes(response);
Client.GetStream().Write(buf, 0, buf.Length);
Client.Close();
}
void ParseMonitorRequest(TcpClient Client, string req)
{
MessageBox.Show("inside parser");
int term_id = Convert.ToInt32(req.Substring(2));
switch (req[1])
{
case '0':
List<MonitorStruct> monitors = tnp_base.GetMonitors(term_id);
foreach (MonitorStruct mon in monitors)
{
}
break;
case '1':
break;
case '2':
break;
case '3':
break;
case '4':
MessageBox.Show("inside 4");
List<TerminalStruct> terminals = tnp_base.GetTerminals();
foreach (TerminalStruct term in terminals)
{
MessageBox.Show("sending response");
MessageBox.Show(string.Format("ID: {0} Address: {1} Comment: {2}", term.TerminalID, term.Address, term.Comment));
//SendResponse(Client, string.Format("ID: {0} Address: {1} Comment: {2}", term.TerminalID, term.Address, term.Comment));
}
break;
}
}
void ParseTerminalRequest(TcpClient Client, string req)
{
}
public TNPClient(TcpClient Client)
{
try
{
tnp_base = new TNPBaseInterraction("127.0.0.1", "tnp", "tnp_user", "tnp123", "3406");
string Request = "";
byte[] buf = new byte[1024];
int Count = 0;
while ((Count = Client.GetStream().Read(buf, 0, buf.Length)) > 0)
{
Request += Encoding.ASCII.GetString(buf, 0, Count);
}
if (Request[0].Equals('0'))
{
ParseMonitorRequest(Client, Request);
}
else
{
ParseTerminalRequest(Client, Request);
}
}
catch (Exception ex)
{
MessageBox.Show("Exception: " + ex.Message);
}
}
}
class TNPServer
{
TcpListener Listener;
int Port = 5252;
public TNPServer(int ServerPort)
{
int MaxThreadsCount = Environment.ProcessorCount * 4;
ThreadPool.SetMaxThreads(MaxThreadsCount, MaxThreadsCount);
ThreadPool.SetMinThreads(2, 2);
Port = ServerPort;
}
public void StartServer()
{
Listener = new TcpListener(IPAddress.Any, Port);
Listener.Start();
while (true)
{
ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(ClientThread), Listener.AcceptTcpClient());
}
}
static void ClientThread(Object StateInfo)
{
new TNPClient((TcpClient)StateInfo);
}
~TNPServer()
{
if (Listener != null)
{
Listener.Stop();
}
}
}
Client side code (this code gives problem):
try
{
TcpClient client = new TcpClient("127.0.0.1", 5365);
if (client.Connected) MessageBox.Show("Connected");
byte[] buf = Encoding.ASCII.GetBytes(tbSendText.Text);
NetworkStream stream = client.GetStream();
stream.Write(buf, 0, buf.Length);
// System.Threading.Thread.Sleep(5000);
//client.ReceiveTimeout = Convert.ToInt32(TimeSpan.FromSeconds(1).TotalMilliseconds);
byte[] buffer = new byte[256];
int Count = 0;
string response = string.Empty;
// while ((Count = client.GetStream().Read(buffer, 0, buffer.Length)) > 0)
//{
Count = stream.Read(buffer, 0, buffer.Length);
response = Encoding.ASCII.GetString(buffer, 0, Count);
//}
stream.Close();
client.Close();
MessageBox.Show(response);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
All messages on server side are shown then i'm not trying to get response on client side. When i'm trying to get response no messages are shown, but connection is established.
In server side, the read loop is blocked forever. You need to read only up to to the length of the text & then parse the request. You can write the length of the text from client side & then write the content.