Im trying to make a TLS/SSL websocket connection using Fleck lib.
https://github.com/statianzo/Fleck (0.9.8.25)
now i got the server startet .
but when a client connects i get the following message.
28-02-2014 19:16:15 [Info] Server started at wss://localhost:8081
28-02-2014 19:18:51 [Debug] Client connected from 127.0.0.1:62543
28-02-2014 19:18:51 [Debug] Authenticating Secure Connection
28-02-2014 19:18:52 [Debug] 0 bytes read. Closing.
anybody got an idea of what im doing wrong ?
Browser: Chrome, version : 33.0.1750.117
class Program
{
private static UTF8Encoding encoding = new UTF8Encoding();
static void Main(string[] args)
{
Connect("wss://localhost:8081").Wait();
}
public static async Task Connect(string uri)
{
Thread.Sleep(1000);
ClientWebSocket webSocket = null;
X509Certificate2 certif = new X509Certificate2(#"QtrackerServer_TemporaryKey.pfx", "jihedgam");
webSocket.Options.ClientCertificates.Equals(certif);
try
{
webSocket = new ClientWebSocket();
await webSocket.ConnectAsync(new Uri(uri), CancellationToken.None);
await Task.WhenAll(Receive(webSocket), Send(webSocket));
}
catch (Exception ex)
{
Console.WriteLine("Exeption: {0}", ex);
}
finally
{
if (webSocket != null)
webSocket.Dispose();
Console.WriteLine();
Console.WriteLine("WebSocket closed.");
}
}
private static async Task Send(ClientWebSocket webSocket)
{
while (webSocket.State == WebSocketState.Open)
{
Console.WriteLine("Write some to send over to server..");
string stringtoSend = Console.ReadLine();
byte[] buffer = encoding.GetBytes(stringtoSend);
await webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Binary, false, CancellationToken.None);
Console.WriteLine("Send: " + stringtoSend);
await Task.Delay(1000);
}
}
private static async Task Receive(ClientWebSocket webSocket)
{
byte[] buffer = new byte[1024];
while (webSocket.State == WebSocketState.Open)
{
buffer = new byte[1024];
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Close)
{
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
}
else
{
Console.WriteLine("Recive: " + Encoding.UTF8.GetString(buffer).TrimEnd('\0'));
}
}
}
}
Related
I built a websocket server in C#. Relevant code is below. The problem is when the if (result.EndOfMessage) is called, the websocket stops listening for any more messages. If any message comes later on, then that message isnt recieved from the client.
How can I receive the messages after a while from the client?
public async Task Listen(int port)
{
try
{
IPAddress serverAddress = IPAddress.Parse("127.0.0.1"); // localhost
_listener = new TcpListener(serverAddress, port);
_listener.Start();
while (true)
{
TcpClient tcpClient = await _listener.AcceptTcpClientAsync();
await Task.Run(() =>
ProcessTcpClientAsync(tcpClient).ConfigureAwait(false));
}
}
catch (SocketException ex)
{
throw new Exception(message, ex);
}
}
private async Task<string> ProcessTcpClientAsync(TcpClient tcpClient)
{
CancellationTokenSource source = new CancellationTokenSource();
try
{
if (_isDisposed)
{
return string.Empty;
}
// get a secure or insecure stream
NetworkStream stream = tcpClient.GetStream();
WebSocketHttpContext context = await _webSocketServerFactory.ReadHttpHeaderFromStreamAsync(stream);
if (context.IsWebSocketRequest)
{
WebSocket webSocket = await _webSocketServerFactory.AcceptWebSocketAsync(context);
await RespondToWebSocketRequestAsync(webSocket, CancellationToken.None);
}
}
catch (ObjectDisposedException ex)
{
// do nothing. This will be thrown if the Listener has been stopped
}
catch (Exception ex)
{
}
}
public async Task RespondToWebSocketRequestAsync(WebSocket webSocket, CancellationToken token)
{
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[BUFFER_SIZE]);
while (true)
{
WebSocketReceiveResult result = await webSocket.ReceiveAsync(buffer, token);
if (result.MessageType == WebSocketMessageType.Close)
{
break;
}
if (result.Count > BUFFER_SIZE)
{
await webSocket.CloseAsync(WebSocketCloseStatus.MessageTooBig,
$"Web socket frame cannot exceed buffer size of {BUFFER_SIZE:#,##0} bytes. Send multiple frames instead.",
token);
break;
}
if (result.EndOfMessage)
{
break;
}
// Process data
SomeMethod();
}
}
I am creating a twiiter stremaing MVC controller. The controller method is implemented as a web socket.
Ref: Connecting with websockets to windows azure using MVC controllerenter link description here
I want to display the twitter stream in the UI. I am using twitterinvl. My code is included below. The stream event MatchingTweetReceived are not getting triggered from the controller method.
Any help on this is highly appreciated.
Controller action method.
public ActionResult About()
{
if (ControllerContext.HttpContext.IsWebSocketRequest)
{
ControllerContext.HttpContext.AcceptWebSocketRequest(DoTalking);
}
return new HttpStatusCodeResult(HttpStatusCode.SwitchingProtocols);
}
Rest of the code
public async Task DoTalking(AspNetWebSocketContext context)
{
try
{
WebSocket socket = context.WebSocket;
while (true)
{
var buffer = new ArraySegment<byte>(new byte[1024]);
WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
if (socket.State == WebSocketState.Open)
{
string userMessage = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);
string outmessage = "Empty";
//userMessage = "You sent: " + userMessage + " at " + DateTime.Now.ToLongTimeString();
Auth.SetUserCredentials("<<credential>>", "<<credential>>", "<<credential>>", "<<credential>>");
var stream = Stream.CreateFilteredStream();
stream.AddTrack("enterhash");
stream.MatchingTweetReceived += (sender, theTweet) =>
{
outmessage = theTweet.Tweet.CreatedBy.ToString() + theTweet.Tweet.CreatedAt + theTweet.Tweet;
buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMessage));
//Console.WriteLine($"Tweet: {theTweet.Tweet.CreatedAt} {theTweet.Tweet}");
socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
};
stream.StartStreamMatchingAllConditions();
Trace.WriteLine(outmessage);
//await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
}
else
{
break;
}
}
}
catch (Exception ex)
{
}
}
I'm currently developing an UWP app which should have capability to be as a TCP server (using ports) so client can connect to it via other device and send requests and server responds with data.
I followed the Socket example on :Microsoft site, and got sample code working (in which server and client are both in same app)
I changed IP addresses and ports so i could use apps on 2 different machines with direct connection, I also made separate simple client application, using sample code from Here
Now problem is as follows: UWP app can successfully communicate with its own client method provided by Microsoft's sample, but is unable to communicate with console client program I made and was running on other. UWP can indeed connect with client and also send data, but it cannot receive data, the function streamReader.ReadLineAsync(); will wait infinitely long and that's all.
How do i make UWP app get the message client is sending and what i might be doing wrong ?
public sealed partial class MainPage : Page
{
static string PORT_NO = "1300";
const string SERVER_IP = "192.168.0.10";
public MainPage()
{
this.InitializeComponent();
outputText.Text = "Helloo";
StartConnection(SERVER_IP, PORT_NO);
//StartClient();
}
public async void StartConnection(string net_aadress, string port_nr)
{
try
{
var streamSocketListener = new StreamSocketListener();
// The ConnectionReceived event is raised when connections are received.
streamSocketListener.ConnectionReceived += this.StreamSocketListener_ConnectionReceived;
// Start listening for incoming TCP connections on the specified port. You can specify any port that's not currently in use.
await streamSocketListener.BindServiceNameAsync(port_nr);
outputText.Text = "server is listening...";
}
catch (Exception ex)
{
Windows.Networking.Sockets.SocketErrorStatus webErrorStatus = Windows.Networking.Sockets.SocketError.GetStatus(ex.GetBaseException().HResult);
outputText.Text = (webErrorStatus.ToString() != "Unknown" ? webErrorStatus.ToString() : ex.Message);
}
}
private async void StreamSocketListener_ConnectionReceived(Windows.Networking.Sockets.StreamSocketListener sender, Windows.Networking.Sockets.StreamSocketListenerConnectionReceivedEventArgs args)
{
string request = "password";
string second;
/*
using (var streamReader = new StreamReader(args.Socket.InputStream.AsStreamForRead()))
{
request = await streamReader.ReadLineAsync();
}
*/
//await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => this.serverListBox.Items.Add(string.Format("server received the request: \"{0}\"", request)));
// Echo the request back as the response.
using (Stream outputStream = args.Socket.OutputStream.AsStreamForWrite())
{
using (var streamWriter = new StreamWriter(outputStream))
{
await streamWriter.WriteLineAsync(request);
await streamWriter.FlushAsync();
}
}
using (var streamReader = new StreamReader(args.Socket.InputStream.AsStreamForRead()))
{
second = await streamReader.ReadLineAsync();
}
using (Stream outputStream = args.Socket.OutputStream.AsStreamForWrite())
{
using (var streamWriter = new StreamWriter(outputStream))
{
await streamWriter.WriteLineAsync(second);
await streamWriter.FlushAsync();
}
}
//await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => this.serverListBox.Items.Add(string.Format("server sent back the response: \"{0}\"", request)));
sender.Dispose();
//await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => this.serverListBox.Items.Add("server closed its socket"));
}
private async void StartClient()
{
try
{
// Create the StreamSocket and establish a connection to the echo server.
using (var streamSocket = new Windows.Networking.Sockets.StreamSocket())
{
// The server hostname that we will be establishing a connection to. In this example, the server and client are in the same process.
var hostName = new Windows.Networking.HostName("localhost");
//this.clientListBox.Items.Add("client is trying to connect...");
await streamSocket.ConnectAsync(hostName, PORT_NO);
//this.clientListBox.Items.Add("client connected");
// Send a request to the echo server.
string request = "Hello, World!";
using (Stream outputStream = streamSocket.OutputStream.AsStreamForWrite())
{
using (var streamWriter = new StreamWriter(outputStream))
{
await streamWriter.WriteLineAsync(request);
await streamWriter.FlushAsync();
}
}
//this.clientListBox.Items.Add(string.Format("client sent the request: \"{0}\"", request));
// Read data from the echo server.
string response;
using (Stream inputStream = streamSocket.InputStream.AsStreamForRead())
{
using (StreamReader streamReader = new StreamReader(inputStream))
{
response = await streamReader.ReadLineAsync();
}
}
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
() =>
{
outputText.Text = "Client got back " + response;
}
);
}
//this.clientListBox.Items.Add("client closed its socket");
}
catch (Exception ex)
{
Windows.Networking.Sockets.SocketErrorStatus webErrorStatus = Windows.Networking.Sockets.SocketError.GetStatus(ex.GetBaseException().HResult);
//this.clientListBox.Items.Add(webErrorStatus.ToString() != "Unknown" ? webErrorStatus.ToString() : ex.Message);
}
}
}
Here is source code for Client application:
{
class Program
{
const int PORT_NUMBER = 1300;
const string SERVER_IP = "192.168.0.10";
static void Main(string[] args)
{
string textToSend = DateTime.Now.ToString();
string password = "Madis on loll";
string receiveddata;
try
{
Console.WriteLine("Client progrm started");
TcpClient client = new TcpClient(SERVER_IP, PORT_NUMBER);
NetworkStream nwStream = client.GetStream();
//System.Threading.Thread.Sleep(500);
//see, how long is packet
byte[] bytesToRead = new byte[client.ReceiveBufferSize];
int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize);
Console.WriteLine("Received : " + Encoding.ASCII.GetString(bytesToRead, 0, bytesRead));
byte[] password2 = ASCIIEncoding.ASCII.GetBytes(password);
Console.WriteLine("Sending : " + password);
nwStream.Write(password2, 0, password2.Length); //sending packet
byte[] receiveddata2 = new byte[client.ReceiveBufferSize];
int receiveddatalength = nwStream.Read(receiveddata2, 0, client.ReceiveBufferSize);
Console.WriteLine("Received : " + Encoding.ASCII.GetString(receiveddata2, 0, bytesRead));
}
catch (Exception ex)
{
Console.WriteLine("Connection error");
}
}
}
}
Found answer myself: main problem is with ReadLineAsync() in Server program: it waits and collects all the stream until it gets end of line character. In this case end of line was never sent and therefore server kept waiting infinitely.
Simplest fix was on Client side by simply adding end of line at the end of packet, like this:
before:
byte[] password2 = ASCIIEncoding.ASCII.GetBytes(password);
Console.WriteLine("Sending : " + password);
nwStream.Write(password2, 0, password2.Length); //sending packet
after:
byte[] newLine = Encoding.ASCII.GetBytes(Environment.NewLine);
byte[] password2 = ASCIIEncoding.ASCII.GetBytes(password);
Console.WriteLine("Sending : " + password);
nwStream.Write(password2, 0, password2.Length); //sending packet
nwStream.Write(newLine,0,newLine.Length);
Also 1 thing worth mentioning: current StreamSocketListener_ConnectionReceived is able to send only once, then it sets outputStream.CanWrite to false.
This can be solved by removing using() from writing and reading functions, like this:
before:
PS! Manually flushing is also replaced with autoflush.
using (Stream outputStream = args.Socket.OutputStream.AsStreamForWrite())
{
using (var streamWriter = new StreamWriter(outputStream))
{
await streamWriter.WriteLineAsync(request);
await streamWriter.FlushAsync();
}
}
after:
Stream outputStream = args.Socket.OutputStream.AsStreamForWrite();
var streamWriter = new StreamWriter(outputStream);
streamWriter.AutoFlush = true;
await streamWriter.WriteLineAsync(request);
Hope it helps someone someday.
I'm trying to implement an async TCP client that sends messages from a queue and listens to the response.
some of the server replies are lost (for example send 7 messages and get only 4 replies) and I don't understand why.
This is not a server issue, since the synchronize version I tested works just fine.
ConcurrentQueue<byte[]> msgQueue = new ConcurrentQueue<byte[]>();
public void Connect()
{
try
{
tcpclnt = new TcpClient();
Console.WriteLine("Connecting.....");
Task.Factory.StartNew(() =>
{
IAsyncResult res = tcpclnt.BeginConnect(_ip, _port, null, null);
if (!res.AsyncWaitHandle.WaitOne(CONNECTION_TIMEOUT_SEC * 1000))
{
tcpclnt.Close();
throw new ApplicationException("timed out trying to connect");
}
tcpclnt.EndConnect(res);
Receive();
byte[] message = null;
while (true)
{
message = null;
msgQueue.TryDequeue(out message);
if (message != null)
{
Stream stm = tcpclnt.GetStream();
Console.WriteLine("Transmitting..... " + Thread.CurrentThread.ManagedThreadId);//for debug
stm.Write(message.ToArray(), 0, message.ToArray().Length);
Receive();
}
}
});
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
//will be called from outside
public void SendMessage(byte[] msg)
{
Console.WriteLine("SendMessage..... " + Thread.CurrentThread.ManagedThreadId);//for debug
msgQueue.Enqueue(msg);
}
private void Receive()
{
SocketError error;
byte[] buffer = new byte[MAX_BUFFER_SIZE];
tcpclnt.Client.BeginReceive(buffer, 0, MAX_BUFFER_SIZE, SocketFlags.None, out error, new AsyncCallback(ReceiveHandler), buffer);
}
private void ReceiveHandler(IAsyncResult ar)
{
System.Console.WriteLine("ReceiveHandler " + Thread.CurrentThread.ManagedThreadId); //for debug
//End current async receive
int bytesRead = tcpclnt.Client.EndReceive(ar);
byte[] resultBuffer = (byte[]) ar.AsyncState;
// do a lot of things with resultBuffer
}
I have a WebSocket server that accepts a stream of binary data from a client and responds with another stream of text data for every 4MB read. The server uses IIS 8 and asp.net web api.
Server
public class WebSocketController : ApiController
{
public HttpResponseMessage Get()
{
if (!HttpContext.Current.IsWebSocketRequest)
{
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
HttpContext.Current.AcceptWebSocketRequest(async (context) =>
{
try
{
WebSocket socket = context.WebSocket;
byte[] requestBuffer = new byte[4194304];
int offset = 0;
while (socket.State == WebSocketState.Open)
{
var requestSegment = new ArraySegment<byte>(requestBuffer, offset, requestBuffer.Length - offset);
WebSocketReceiveResult result = await socket.ReceiveAsync(requestSegment, CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Close)
{
// Send one last response before closing
var response = new ArraySegment<byte>(Encoding.UTF8.GetBytes("Server got " + offset + " bytes\n"));
await socket.SendAsync(response, WebSocketMessageType.Text, true, CancellationToken.None);
// Close
await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
break;
}
offset += result.Count;
if (offset == requestBuffer.Length)
{
// Regular response
var response = new ArraySegment<byte>(Encoding.UTF8.GetBytes("Server got 4194304 bytes\n"));
await socket.SendAsync(response, WebSocketMessageType.Text, true, CancellationToken.None);
offset = 0;
}
}
}
catch (Exception ex)
{
// Log and continue
}
});
return new HttpResponseMessage(HttpStatusCode.SwitchingProtocols);
}
}
The c# client uses the ClientWebSocket class to connect to the server and send requests. It creates a task for receiving responses from the server that runs in parallel with the request sending. When it is done sending the requests it calls CloseAsync on the socket and then waits for the Receive task to complete.
Client
using System;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace WebSocketClient
{
class Program
{
static void Main(string[] args)
{
try
{
CallWebSocketServer().Wait();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
static async Task CallWebSocketServer()
{
using (ClientWebSocket socket = new ClientWebSocket())
{
await socket.ConnectAsync(new Uri("ws://localhost/RestWebController"), CancellationToken.None);
byte[] buffer = new byte[128 * 1024];
Task receiveTask = Receive(socket);
for (int i = 0; i < 1024; ++i)
{
await socket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Binary, true, CancellationToken.None);
}
await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
receiveTask.Wait();
Console.WriteLine("All done");
}
}
static async Task Receive(ClientWebSocket socket)
{
try
{
byte[] recvBuffer = new byte[64 * 1024];
while (socket.State == WebSocketState.Open)
{
var result = await socket.ReceiveAsync(new ArraySegment<byte>(recvBuffer), CancellationToken.None);
Console.WriteLine("Client got {0} bytes", result.Count);
Console.WriteLine(Encoding.UTF8.GetString(recvBuffer, 0, result.Count));
if (result.MessageType == WebSocketMessageType.Close)
{
Console.WriteLine("Close loop complete");
break;
}
}
}
catch (Exception ex)
{
Console.WriteLine("Exception in receive - {0}", ex.Message);
}
}
}
}
The problem is that the client blocks at the CloseAsync call.
What would be the correct way of gracefully closing the WebSocket in this scenario?
Figured this out.
Server
Basically, I had to call the ClientWebSocket.CloseOutputAsync (instead of the CloseAsync) method to tell the framework no more output is going to be sent from the client.
await socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
Client
Then in the Receive function, I had to allow for socket state WebSocketState.CloseSent to receive the Close response from the server
static async Task Receive(ClientWebSocket socket)
{
try
{
byte[] recvBuffer = new byte[64 * 1024];
while (socket.State == WebSocketState.Open || socket.State == WebSocketState.CloseSent)
{
var result = await socket.ReceiveAsync(new ArraySegment<byte>(recvBuffer), CancellationToken.None);
Console.WriteLine("Client got {0} bytes", result.Count);
Console.WriteLine(Encoding.UTF8.GetString(recvBuffer, 0, result.Count));
if (result.MessageType == WebSocketMessageType.Close)
{
Console.WriteLine("Close loop complete");
break;
}
}
}
catch (Exception ex)
{
Console.WriteLine("Exception in receive - {0}", ex.Message);
}
}
i suggest you to look at these links:
asynchronous server:
https://msdn.microsoft.com/en-us/library/fx6588te%28v=vs.110%29.aspx
asynchronous client:
https://msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx
recently i implementled something similar with these links as an example. the methods "BeginReceive" (for server) and "BeginConnect" (for client) start each a new thread. so there won't be anything that blocks