I'm opening up a tcp connection to a server which is easy enough to do but I need a way to keep that socket open without having to call net.createConnection(port, host) again and again.
What I'm trying to implement is a socket server which accepts multiple connections then channels the requests through the one socket as mentioned above. I then need to channel the response to the correct socket. However, the only issue I'm having is to maintain an open socket which I'm trying to create outside the listening server code.
I've approached it with the Singleton pattern to create the socket..
var Singleton = (function() {
var socket = null;
function connectToHost(port, host) {
socket = net.createConnection(port, host);
return socket;
}
return {
connectToHost: connectToHost
};
})();
But from what I can see, on Event('end') that socket is no longer writable. If I reconnect the socket.
socket.on('end', function() {
socket = Singleton.connectToHost(port, host);
});
the same thing will happen on Event('end').
How can I approach this so that I can create and maintain one socket connection?
A late response to this.
If I understand your question correctly, are you trying to do something like this?
socket.on('close', function() {
socket.connect(port, host);
});
According to the net Node.js v.0.12.0 documentation
It might work, but it will hammer the server pretty badly, so a setTimeout might be wise.
I'm curious: what did you end up with in the end?
It sounds like you want a mux/demux (multiplexer/demultiplexer) in front of your server which, presumably, replies in such a way as the frontend can properly route the reply.
There's nothing in TCP to support this so you'll have to write it yourself or find one already written. http://www.google.com/search?q=tcp+multiplexer
This link looks promising: http://sourceforge.net/projects/tcpmultiplexer/
(Don't confuse what you're looking for with "tcpmux" on port #1; that's completely different.)
Related
I am creating a UDP-proxy in go, but while doing some load test using iperf, I start to get this error:
socket: too many open files
After searching and testing, I found that if I create a pool using a map of opening connections being the key *net.UDPAddr.String() and the value an instance of UDP-proxy containing an *net.UDPConn, I am available to reuse existing connection in case the client address is the same:
var clients map[string]*UDPProxy.UDPProxy = make(map[string]*UDPProxy.UDPProxy)
This block of code looks something like:
// wait for connections
for {
n, clientAddr, err := conn.ReadFromUDP(buffer)
if err != nil {
log.Println(err)
}
counter++
if *d {
log.Printf("new connection from %s", clientAddr.String())
}
fmt.Printf("Connections: %d, clients: %d\n", counter, len(clients))
proxy, found = clients[clientAddr.String()]
if !found {
// make new connection to remote server
proxy = UDPProxy.New(conn, clientAddr, raddr_udp, *d)
clients[clientAddr.String()] = proxy
}
go proxy.Start(buffer[0:n])
}
This seems to be working, but the problem I have now, is that I need find a way of expiring,cleaning the map when the client exists or is not using any more the proxy so that I could avoid having multiple unused connections.
Any idea how of could I improve this or even better, how could I replace totally the map, I don't know if channels could be help full?
Thanks in advance.
Since you are creating UDP proxies, you probably know that you have to come up with your own solution for deciding when to "terminate" the proxy session. The session is just an abstraction when it comes to UDP - unless the UDPProxy package you're using has an established mechanism already.
Depending on why you are creating UDP proxies, it might be easy to arbitrarily cleanup connections ...
So if you know that a client is exiting, call the Close() method on the proxy (assuming there is one) and use delete on the map entry.
How to decide that a client is exiting is up to you. Could use a slice as a FIFO, or pick one randomly, or try setting timers for each.
Long story short, i want to specify to the client a timeout when invoking the lookup method. The reason i'm doing this is that my application should give the user the possibility to specify the adress and the port of the remote server himself. So in case of wrong config (e.g address like 124.0.0.1), the client will have to wait for a hole minute for tha app to respond.
I've tried the following properties but in vain :
-Dsun.rmi.transport.tcp.handshakeTimeout=10000
-Dsun.rmi.transport.tcp.responseTimeout=10000
-Dsun.rmi.transport.proxy.connectTimeout=10000
The only solution that worked for me is to implement the RMIClientSocketFactory, create a socket inside the createSocket method and specify the time out for this socket like this
new RMIClientSocketFactory() {
#Override
public Socket createSocket(String host, int port)
throws IOException {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(host, port), 10000);
return socket;
}
};
But i don't want to use this solution cause it is ugly and risked.
Any suggestions?
Thanks
I have a problem in the WSASocket programming. I want to do some trick at server side so that
it could hold the client side wait for a while in the WSAWaitForEvents() function waiting for
FD_CONNECT event.
Details are as follows:
At the client side, the socket is non-blocking mode. And it tries to connect to the server. It main code is something like:
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
WSAEvent hEvent = WSACreateEvent();
WSAEventSelect(s, hEvent, FD_CONNECT); //this also make socket non-blocking mode.
connect(s, &someserveraddr, sizeof(someserveraddr)); //connect to some server in non-block mode
WSAWaitForMultipleEvents(1, &hEvent, TRUE, WSA_INFINITE, FALSE); //this will block until success or faile
At the server side, one the server sees a connection from that client, it will do something special which will also take sometime, for example: calling doSomethingLengthy(), So I want to hold the client side blocking at function WSAWaitForMultipleEvents(...) until the server finishes that task. But I don't know how to achieve this. Usually, the server code would like:
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
bind(s, &someaddress, sizeof(someaddress));
listen(s, 5);
SOCKET acceptSocket = accept(s, &someotheraddress, sizeof(someotheraddress));
The problem is that, I don't know where/when to call doSomethingLengthy(). I know that once listen() is done, the client will be notified done and WSAWaitForMultipleEvents() will return. But I cannot call doSomethingLengthy() before listen() otherwise the client side connect() will fail.
You can't. The server end of connect happens before the server gets to see the accepted socket, via the backlog queue.
FD_CONNECT tells you when the socket has connected, but FD_WRITE tells you when you are allowed to send data over the connection. So try waiting for FD_WRITE instead (do note that you can get FD_WRITE multiple times during a connection's lifetime, but you will always get it after a successful connect() in addition to FD_CONNECT).
Okay, I want to send a UDP packet to an IP, and then receive it.
As I can't get it to work, I have to ask for assistance.
I want it to work on 1 app, meaning client and server is on the same application.
I currently got it working with Audio sending and receiving on the same app (using sample codes and stuff).
And the thing I can´t understand is just the UDP, and probably Sockets.
It seems simple, but I can´t get it to work.
So if I can get a very simple sample, like:
"UDP Send "hello" to IPofchoice"
"UDP receive "data" from IPofchoice"
Messagebox.show("decoded(data));
Well hope you get what I mean.
EDIT:
Here is my "example" which doesn´t work at all.
void VoiceChat_KeyPress(object sender, KeyPressEventArgs e)
void VoiceChat_KeyPress(object sender, KeyPressEventArgs e)
{
string text = "Hello";
byte[] send_buffer = Encoding.ASCII.GetBytes(text);
otherPartyIP = new IPEndPoint(IPAddress.Parse(txtCallToIP.Text), 1450);
udpClientKey.Send(send_buffer, send_buffer.Length, "127.0.0.1", 1450);
byte[] byteData = udpClientKey.Receive(ref otherPartyIP);
MessageBox.Show(otherPartyIP.Address.ToString());
MessageBox.Show(System.Text.Encoding.ASCII.GetString(byteData));
}
Where txtCallToIP.tex = the ip i write, which is 127.0.0.1 currently.
This i solved.
To have a client and server in UDP it´s very easy, though a bit dangerous, as you don´t know for sure if it´s working or not unless you test it (UDP just send and don´t care about anything else).
So basically to do it.
Client.Send(buffer,0,buffer.size,IPAdress,Port);
byte[] rec = Client.Receive(ref IPAdress);
To receive you must have bind it to an IP, so you can just bind it to listen to Any ipadress,
The port however needs to be set (i think), and you want to do that, as listening to everything there is, is not a good idea.
So ref IPAdress will be that listening IP and Port.
So it´s very easy to set up. And you can use the same UDPClient for both receiving and sending if you want, though it´s probably better to have 2 separate .
I've been having some problems with the below code that I've pieced together. All the events work as advertised however, when a client drops off-line without first disconnecting the close event doesn't get call right away. If you give it a minute or so it will eventually get called. Also, I find if I continue to send data to the client it picks up a close event faster but never right away. Lastly, if the client gracefully disconnects, the end event is called just fine.
I understand this is related to the other listen events like upgrade and ondata.
I should also state that the client is an embedded device.
client http request:
GET /demo HTTP/1.1\r\n
Host: example.com\r\n
Upgrade: Websocket\r\n
Connection: Upgrade\r\n\r\n
//nodejs server (I'm using version 6.6)
var http = require('http');
var net = require('net');
var sys = require("util");
var srv = http.createServer(function (req, res){
});
srv.on('upgrade', function(req, socket, upgradeHead) {
socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
'Upgrade: WebSocket\r\n' +
'Connection: Upgrade\r\n' +
'\r\n\r\n');
sys.puts('upgraded');
socket.ondata = function(data, start, end) {
socket.write(data.toString('utf8', start, end), 'utf8'); // echo back
};
socket.addListener('end', function () {
sys.puts('end'); //works fine
});
socket.addListener('close', function () {
sys.puts('close'); //eventually gets here
});
});
srv.listen(3400);
Can anyone suggest a solution to pickup an immediate close event? I am trying to keep this simple without use of modules. Thanks in advance.
close event will be called once TCP socket connection is closed by one or another end with few complications of rare cases when system "not realising" that socket been already closed, but this are rare cases. As WebSockets start from HTTP request server might just keep-alive till it timeouts the socket. That involves the delay.
In your case you are trying to perform handshake and then send data back and forth, but WebSockets are a bit more complex process than that.
The handshake process requires some security procedure to validate both ends (server and client) and it is HTTP compatible headers. But different draft versions supported by different platforms and browsers do implement it in a different manner so your implementation should take this in account as well and follow official documentation on WebSockets specification based on versions you need to support.
Then sending and receiving data via WebSockets is not pure string. Actual data sent over WebSockets protocol has data-framing layer, which involves adding header to each message you send. This header has details over message you sending, masking (from client to server), length and many other things. data-framing depends on version of WebSockets again, so implementations will vary slightly.
I would encourage to use existing libraries as they already implement everything you need in nice and clean manner, and have been used extensively across commercial projects.
As your client is embedded platform, and server I assume is node.js as well, it is easy to use same library on both ends.
Best suit here would be ws - actual pure WebSockets.
Socket.IO is not good for your case, as it is much more complex and heavy library that has multiple list of protocols support with fallbacks and have some abstraction that might be not what you are looking for.