According to MSDN I have following code to create Client/Server communication with TCP/IP StreamSockets.
Server:
public async void Start(int port)
{
try
{
//Create a StreamSocketListener to start listening for TCP connections.
StreamSocketListener socketListener = new StreamSocketListener();
//Hook up an event handler to call when connections are received.
socketListener.ConnectionReceived += SocketListener_ConnectionReceived;
//Start listening for incoming TCP connections on the specified port. You can specify any port that's not currently in use.
await socketListener.BindServiceNameAsync(port.ToString());
}
catch (Exception ex)
{
Debug.WriteLine("SocketServer could not start. " + ex.ToString());
}
}
private async void SocketListener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
try
{
string request;
//Read line from the remote client.
using (Stream inStream = args.Socket.InputStream.AsStreamForRead())
{
using (StreamReader reader = new StreamReader(inStream))
{
request = await reader.ReadLineAsync();
}
}
// Process command and get response
SocketResponse response = ProcessRequest(request);
string responseString = JsonHelper.ToJson<SocketResponse>(response);
//Send the line back to the remote client.
using (Stream outStream = args.Socket.OutputStream.AsStreamForWrite())
{
using (StreamWriter writer = new StreamWriter(outStream))
{
await writer.WriteLineAsync(responseString);
await writer.FlushAsync();
}
}
}
catch(Exception ex)
{
Debug.WriteLine("SocketListener failed." + ex.ToString());
}
}
Client:
private async Task Start(int responseTimeout)
{
CancellationTokenSource cts = new CancellationTokenSource();
try
{
cts.CancelAfter(responseTimeout);
//Create the StreamSocket and establish a connection to the echo server.
socket = new StreamSocket();
//The server hostname that we will be establishing a connection to. We will be running the server and client locally,
//so we will use localhost as the hostname.
HostName serverHost = new HostName(hostName);
//Every protocol typically has a standard port number. For example HTTP is typically 80, FTP is 20 and 21, etc.
//For the echo server/client application we will use a random port 1337.
string serverPort = port.ToString();
await socket.ConnectAsync(serverHost, serverPort).AsTask(cts.Token);
}
catch
{
socket.Dispose();
}
}
public async Task<SocketResponse> SendCommand(SocketCommand command, int responseTimeout = 2000)
{
// Connect to socket first
await Start(responseTimeout);
//Write data to the echo server.
using (Stream streamOut = socket.OutputStream.AsStreamForWrite())
{
using (StreamWriter writer = new StreamWriter(streamOut))
{
// Serialize command to json and send
string request = JsonHelper.ToJson<SocketCommand>(command);
await writer.WriteLineAsync(request);
await writer.FlushAsync();
}
}
//Read data from the echo server.
using (Stream streamIn = socket.InputStream.AsStreamForRead())
{
using (StreamReader reader = new StreamReader(streamIn))
{
string responseString = await reader.ReadLineAsync();
return JsonHelper.FromJson<SocketResponse>(responseString);
}
}
}
I am encountering two issues with my code:
- I have to establish connection from client side before every request. What is the reason?
- When I am sending bigger response from server (string is 3kb) client waits for the response infinitely, however server responded quickly. Moreover, if server is closed, response is read by client. What's going wrong with this?