Sunday, 15 July 2012

azure - ASP.NET close connection before sending all websocket data to client -



azure - ASP.NET close connection before sending all websocket data to client -

i wrote simple asp.net websocket handler gateway between remote info processing server , clients. tested in local machine (win8, iis express 8) , worked well. in azure website, asp.net closes connection before sending websocket info client.

following info transfer code:

internal class websocketstreamtransfer{ public websocketstreamtransfer(cancellationtoken disconnectiontoken){ disconnectiontoken = disconnectiontoken; } private cancellationtoken disconnectiontoken{ get; set; } public async task acceptwebsocketconnection(websocketcontext context) { if (context == null) throw new argumentnullexception("context"); websocket websocket = context.websocket; if (websocket == null) throw new socksoverhttpexception("null websocket"); using(iconnection conn = connectionmanagerfactory.connectionmanager.createconnection(guid.newguid().tostring())) { seek { disconnectiontoken.register(conn.close); taskcompletionsource<bool> tcs = new taskcompletionsource<bool>(null); await task.whenany(senddatatoremoteserver(conn, websocket, disconnectiontoken, tcs), senddatatoclient(conn, websocket, disconnectiontoken, tcs.task)); } catch(exception e) { logger.logexception(e); } } } internal static async task senddatatoremoteserver(iconnection conn, websocket websocket, cancellationtoken canceltoken, taskcompletionsource<bool> tcs) { seek { arraysegment<byte> buffer = new arraysegment<byte>(new byte[applicationconfiguration.getdefaultbuffersize()]); while (isconnected(conn, canceltoken, websocket)) { websocketreceiveresult result = await websocket.receiveasync(buffer, canceltoken); if (websocket.state == websocketstate.open) { if (result.messagetype == websocketmessagetype.binary) { if (result.count > 0) { if (isconnected(conn, canceltoken, websocket)) { int numread = await conn.senddata(buffer.array, 0, result.count, canceltoken); if (numread > 0) { tcs.trysetresult(true); // notify senddatatoclient can go on }else{ logger.logerror("client not send plenty info remote connection built"); return; } } else { logger.loginformation("senddatatoremoteserver: cancel send info remote server due connection closed"); } } else logger.loginformation("receive empty binary message"); } else if (result.messagetype == websocketmessagetype.text) { logger.logerror("receive unexpected text message"); return; } else { logger.loginformation("receive close message"); await websocket.closeasync(websocketclosestatus.normalclosure, "close connection", canceltoken); return; } } else { logger.loginformation("senddatatoremoteserver: websocket connection closed client"); return; } } }finally{ tcs.trysetresult(true); } } internal static async task senddatatoclient(iconnection conn, websocket websocket, cancellationtoken canceltoken, task connectedtask) { await connectedtask; while (isconnected(conn, canceltoken, websocket)) { byte[] info = await conn.receivedata(canceltoken); if (data.length <= 0) { logger.loginformation("senddatatoclient: empty info remote server"); return; } if (isconnected(conn, canceltoken, websocket)) { await websocket.sendasync(new arraysegment<byte>(data), websocketmessagetype.binary, true, canceltoken); } else { logger.loginformation("senddatatoclient: cancel send info client due connection closed"); } } } internal static bool isconnected(iconnection conn, cancellationtoken canceltoken, websocket websocket) { bool socketconnected = websocket.state == websocketstate.open; homecoming socketconnected && conn.connected && !canceltoken.iscancellationrequested; } }

problem scenario:

senddatatoremoteserver waiting client info , client has not info send yet

senddatatoclient receive empty info remote server, means remote server start closing connection. finish senddatatoclient

acceptwebsocketconnection finish because task.whenany(senddatatoremoteserver(conn, websocket, disconnectiontoken, tcs), senddatatoclient(conn, websocket, disconnectiontoken, tcs.task))

expect asp.net send info before close tcp connection asp.net close connection (azure).

a websocket message can split in different frames. not checking if message completed. code sending info form ws connection other should this:

websocketreceiveresult result = null; { result = await source.receiveasync(buffer, cancellationtoken.none); var sendbuffer = new arraysegment<byte>(buffer.array, buffer.offset, result.count); await target.sendasync(sendbuffer, result.messagetype, result.endofmessage, cancellationtoken.none); } while (!result.endofmessage);

you have check endofmessage property, , go on reading while message not completed.

it works in local computer because locally no affected buffering in same way, or because messages trying smaller.

asp.net azure websocket

No comments:

Post a Comment