socket.io properly disconnect a socket from unity side - unity3d

I am trying to properly close a socket of socket.io that got open from unity side. My problem is that, even though I expect one log information from unity side (server disconnected) and one in server side, I get my "bye" message, multiples of times, around 10 times, from server side (unity side publishes only 1 time, as expected). Could you please tell me how could I prevent this overhead, and why the repetition is happening?
On unity side, using a free scoket.io plugin, I have the code:
void Start () {
socket = GetComponent<SocketIOComponent> ();
socket.On ("open", OnOpen);
socket.On ("disconnect", OnDisconnect);
}
void OnDisconnect(SocketIOEvent e){
Debug.Log ("server disconnected!");
socket.Close ();
}
in server side, my test code is:
io.on('connection', function(socket) {
console.log('bye...');
socket.disconnect(true);
});

Related

UWP Socket.InputStream.ReadAsync Hangs

I'm having trouble with UWP. I am trying to bind a StreamSocketListener to act as a small web server but after 20 or so connections the ReadAsync function hangs and the application eventually closes without an error.
Here is the code I'm using:
private const uint bufferSize = 1024;
private int port = 9000;
public async void Start()
{
StreamSocketListener listener = new StreamSocketListener();
listener.ConnectionReceived += async (sender, args) =>
{
string request = null;
using (IInputStream input = args.Socket.InputStream)
{
byte[] data = new byte[bufferSize];
IBuffer buffer = data.AsBuffer();
uint bytesRead = bufferSize;
while (bytesRead == bufferSize)
{
IBuffer result = await input.ReadAsync(buffer, bufferSize, InputStreamOptions.Partial);
request += Encoding.ASCII.GetString(result.ToArray());
bytesRead = buffer.Length;
}
processRequest(getPath(request), args.Socket.OutputStream);
}
};
await listener.BindServiceNameAsync(port.ToString());
}
You'd better dispose the disused connection in time. When your app receive a new connection, you could release the previous connection in its ConnectionReceived event handler. You could see the official code sample also does the same thing. SocketActivityStreamSocket/cs/Server
I am using similar code (I found it somewhere online) on my Raspberry Pi 3 acting as a simple web server, yeah.. it is very frustrated. Indeed, I ran into the same issue and I did use "args.Socket.Dispose()" on each request to solve PART OF THE PROBLEM.
I have a windows service client connecting to my Pi simple web server every 30 seconds and my Pi background service just hangs after around 1.5 to 2 hours. After debugging for many hours, I tried to remove the "await" from input.ReadSync, also make sure that your ProcessRequest doesn't do any async/await. It solved my problem, the server becomes stable without hangging. For me it is okay, since I only have one client, so Sync or Async doesn't really matter to me.
One weird problem though... it seems like randomly during the day, the "request" string will receive some garbage instead of the real HTTP request. I still haven't figured out why. BTW, There is a very good open source project on GitHub called "Catnap.Server", it seems to look pretty powerful. I haven't tried it but if you look at that implementation, they are using Streamreader instead of ReadAsync.
My windows service client has been working perfectly for 3 years when it was connecting to my old version of Raspberry Pi which ran on NOOBS linux, Apache and PHP. It was rock solid stable... just want to give Win 10 IoT a try and we have to implement our own web server!!??? My experience so far isn't that pleasant honestly.

how does Netty server know when client is disconnected?

I am making Netty Server that satisfies the following conditions:
Server needs to do transaction process A, when it receives packet from its client.
After finishing transaction, if it is still connected, it sends back return message to client. If not, do some rollback process B.
But my problem is that when I send back to client, the Server does not know wheter it is still connected or not.
I've tried following codes to figure out its connection before sending messages. However it always succeeds even though client already closed its socket. It only fails when client process is forcibly killed (e.g. Ctrl+C)
final ChannelFuture cf = inboundChannel.writeAndFlush(resCodec);
cf.addListener(new ChannelFutureListener() {
#Override
public void operationComplete(ChannelFuture future) {
if (future.isSuccess()) {
inboundChannel.close();
} else {
try {
// do Rollback Process B Here
}
}
});
I thought this is because of TCP protocol. If client disconnect gracefully, then FIN signal is sent to server. So it does think writeAndFlush succeeds somehow even when it doesn't.
So I've tried following code too, but these have the same result (always return true)
if(inboundChannel.isActive()){
inboundChannel.writeAndFlush(msg);
} else{
// do RollBack B
}
// Similar codes using inboundChannel.isOpen(), inboundChannel.isWritable()
Neither 'channelInactive' event nor 'Connection Reset by Peer' exception occur in my case.
This is the part of Netty test client code that I used.
public void channelActive(ChannelHandlerContext ctx) {
ctx.writeAndFlush(message).addListener(ChannelFutureListener.CLOSE);
}
How can I notice disconnection at the time that I want to reply?
May be you should override the below method and see if the control goes here when channel is closed.
#Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// write cleanup code
}
I don't think its possible to track that whether client is connected or not in netty because there is an abstraction between netty and client.

AndroidAsync TCP -- proper way to detect socket is no longer available using write?

I am wondering what is the proper way to check on the client side that a TCP socket opened using the AndroidAsync library is no longer available? This is in the case the (plain TCP, non-AndroidAsync) server did not initiate explicitly closing the socket (so the ClosedCallback is not invoked). For instance, when the server has been cold rebooted.
It seems that the DataCallback is available only when the server sends back data and can't be used to receive error messages.
It seems to me also that
Util.writeAll(socket, (byte[]) payload.array(), new CompletedCallback()
{
#Override
public void onCompleted(Exception ex)
{
if (ex != null)
{
Log.e(TAG, "write failed with ex message= " + ex.getMessage());
throw new RuntimeException(ex);
}
}
});
does not throw an Exception either.
So at this point I'm not sure how to detect the socket is no longer available even if the client periodically writes data to it.
It will throw an IOexception if you send enough data or call it enough times. It won't throw on the first call due to TCP buffering at both ends.
I ended up implementing some sort of a "ping"-alike periodic check. The client opens and immediately closes a TCP connection to the very same port using a plain Java NIO socket call (not using AndroidAsync). If that one times out, it is assumed that the connection has been lost, and a recovery attempt is made once it succeeds again. This periodic check is performed only when the app has focus, or is just awakened. This is clearly a far from ideal workaround but it seems to work for my purposes.
You could use the closed/end callbacks
socket.setClosedCallback(new CompletedCallback()
{
#Override
public void onCompleted(Exception ex)
{
}
});
socket.setEndCallback(new CompletedCallback()
{
#Override
public void onCompleted(Exception ex)
{
}
});

keep all connected clients' ip in netty

My TCP server uses netty.The situation is: When a client connects to the server,I will save the client's ip in a global variable(such as a Map); When the client is disconnected,I will remove the IP from the map.
I used channelConnected() and channelDisconnected() method in SimpleChannelHandler.But my problem is ,some times the channelDisconnected() method cannot catch the event when I think the client is disconnected(maybe the computer closed,or the client process closed,or some other situations...) Can you give me some suggestions.
Just use DefaultChannelGroup which will automatically remove the Channel from it when it was closed.
Alternative you can register a ChannelFutureListener to the Channels close future to do the removal from your map.
Something like this:
channel.getCloseFuture().addListener(new ChannelFutureListener() {
public void operationCompleted(ChannelFuture f) {
map.remove(f.getChannel());
}
});

Any off the shelf app to rebroadcast tcp packets?

I am working with a 3rd party device which opens a tcp port that only allows one connection at a time. If my app connects to the port, all other connections are denied.
I'd like to find an app that basically connects to this port, then allows others to connect to it on a different port.
Any data sent out of the device's port is then rebroadcast to any connected client.
I know how to write such an app, but it seems like it would be something someone else has already thought off and written it & shared, and I could avoid taking the time to write it.
basicaly code would be:
1) start a tcp socket server, binding to TO_PORT (clients connect to this)
2) connect as a client to DEVICE_IP:DEVICE_PORT
3) when data is read into a buffer from DEVICE_IP:DEVICE_PORT, the buffer content is resent to each connected client.
4) everything else that makes it a stable, working program.
This is for windows, and I'd prefer it not require a java install.
My google skills have failed me.
Anyone know of such an app?
Not a complete solution for you, but might be interesting, though
http://www.codeproject.com/KB/IP/serversocket.aspx
http://www.codeproject.com/KB/IP/UniversalTCPSocketClass.aspx
Guess I'll answer my own question.
I implemented the solution my self.
Key points to my solution:
A class named IPClient which wraps up a TcpClient instance, uses async model of calling TcpClient.BeginConnect, BeginRead, etc. It has a Timer used for reconnecting if it loses connection.
This is the class that connects to the device.
It's public interface would look something like this:
public class IPClient{
public event EventHandler<MyConnectedArgs> Connected;
public event EventHandler<MyDisconnectedArgs>Disconnected;
public event EventHandler<MyDataReceivedArgs> DataReceived;
public bool Connect(string address, int port){...}
public bool Disconnect() {...}
}
To open the port that would allow other clients to connect, I used this library: http://codeproject.com/KB/IP/BasicTcpServer.aspx and modified it a bit.
It's job was to open a port, accept connections, and do the following:
in the Connected handler, start the listening port
in the Disconnected handler, stop the listening port
in the DataReceived handler, broadcast the data to any connected clients.
I'll leave out the rest of the boring details, but say it wasn't "too hard", and eventually I just had to roll my own.
command line usage: myapp.exe remote_addr remote_port listen_port
psuedocode/main idea of my program main:
static int Main(string[] args){
//SetConsoleCtrlHandler(my callback re: ctrl+C,etc)
//get command line params
var ipClient = new IPClient();
var myprovider = MyTcpServiceProvider();
var server = new TcpServer(myProvider, listenPort);
ipClient.Connected += (sender, e) => server.Start();
ipClient.Disconnected += (sender,e) => server.Stop();
ipClient.DataReceived += (sender,e)=> provider.BroadcastToClients(e.Data);
ipClient.Connect(remoteAddress, remotePort);
//wait for Ctrl+C or program exit
//shutdown code,etc
return 0;
}