|
|
Home » U++ Library support » U++ Core » How to close the websocket connection
|
|
|
|
Re: How to close the websocket connection [message #49459 is a reply to message #48944] |
Wed, 14 February 2018 19:17 |
uppjj
Messages: 9 Registered: February 2018 Location: France
|
Promising Member |
|
|
Hello
I got the same problem, "Close" put my websocket client in infinite loop.
Server receives the "Close" message from the client but does not actually send the response, because it is in non-blocking mode.
I just do this change in uppsrc/core/WebSocket.cpp , function "out":
// while(IsBlocking() && socket->IsOpen() && !IsError() && out_queue.GetCount())
while((IsBlocking() || (s[0] == CLOSE)) && socket->IsOpen() && !IsError() && out_queue.GetCount())
and got "Close" working well...
[Updated on: Wed, 14 February 2018 21:10] by Moderator Report message to a moderator
|
|
|
|
Re: How to close the websocket connection [message #49528 is a reply to message #49487] |
Sat, 24 February 2018 15:59 |
uppjj
Messages: 9 Registered: February 2018 Location: France
|
Promising Member |
|
|
thanks for your reply Mirek
In my case the server no longer called do () after launching close (), I should have better read the documentation!
The problem is rather client side, see below.
I encountered several difficulties to write a client application (IoT) with Websocket class for the real world of the web, but it does not miss much:
1) the connection header is currently fixed, it is essential to be able to modify it
=> it could be something like a Vector <String> to adapt before connecting.
2) Need a public function for really close the socket. Websoket :: Close does not close the socket but sends a request to the server.
If it does not respond for some reason, the client loops indefinitely (my first problem !)
I replaced the Close by Disconnect (), and added a new Close ():
void Disconnect (const String & msg = Null); // old Close (), just a message to the server
void Close () {socket-> Close ();} // real TCP close, even is server is sleeping...
3) Sending Masked requests is not available. This works:
add this function in class WebSocket (Inet.h) :
void SendTextMasked(const String& data) { SendRaw(MASK|FIN|TEXT, data); }
Change SendRaw() in WebSocket.cpp :
void WebSocket::SendRaw(int hdr, const String& data)
{
if(IsError())
return;
ASSERT(!close_sent);
LLOG("Send " << data.GetCount() << " bytes, hdr: " << Format("%04X",hdr));
// mask detect
int LocMask = (hdr & MASK)?0x80:0;
hdr &= 0xFF;
//---- header construct
// opcode
String header;
header.Cat(hdr);
// Length
int len = data.GetCount();
if(len > 65535) {
header.Cat(LocMask | 127);
header.Cat(0);
header.Cat(0);
header.Cat(0);
header.Cat(0);
header.Cat(byte(len >> 24));
header.Cat(byte(len >> 16));
header.Cat(byte(len >> );
header.Cat(byte(len));
}
else
if(len > 125) {
header.Cat(LocMask | 126);
header.Cat(byte(len >> );
header.Cat(byte(len));
}
else
header.Cat(LocMask |(int)len);
if (LocMask)
{
//add masking-key
byte Cle[4];
Cle[0] = Random();
Cle[1] = Random();
Cle[2] = Random();
Cle[3] = Random();
for(int i = 0; i < 4; i++) header.Cat(Cle[i]);
//---- send header with mask
Out(header);
//---- send masked data
if(data.GetCount() != 0)
{
char buf[32768];
int n = data.GetCount();
for(int i = 0; i < n; i++)
buf[i] = data[i] ^ (byte) Cle[i & 3];
Out(String(buf,n));
}
}
else
{
//---- send header (not masked)
Out(header);
//--- send data (not masked)
if(data.GetCount() != 0)
Out(data);
}
}
hope this can help
|
|
|
|
|
|
Re: How to close the websocket connection [message #49555 is a reply to message #49554] |
Wed, 28 February 2018 23:27 |
|
Klugier
Messages: 1083 Registered: September 2012 Location: Poland, Kraków
|
Senior Contributor |
|
|
Hello Mirek,
Why not to keep request_headers as Vector:
Vector<String> request_headers;
request_headers = {
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"",
"Accept-Language: cs,en-US;q=0.7,en;q=0.3",
...
};
// The user can add custom headers to the vector with more straight forward wait. Moreover user will not be obligated to remember about /r/n.
auto header = web_socket.StandardHeaders();
header.Add("Custom-header: data");
// Deletation is also trivial of any of the standard headers.
request_headers.Remove(1); // Remove ""Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"",", I don't need it!
// The set method also needs to be change
web_socket.RequestHeaders(request_headers);
\r\n can be added to the lines while processing. These approch is more flexible than String implementatino. Please let me know what do you think?
Sincerely,
Klugier
U++ - one framework to rule them all.
[Updated on: Wed, 28 February 2018 23:40] Report message to a moderator
|
|
|
Re: How to close the websocket connection [message #49560 is a reply to message #49555] |
Thu, 01 March 2018 16:55 |
uppjj
Messages: 9 Registered: February 2018 Location: France
|
Promising Member |
|
|
hello all
Mirek,
-in SenRaw you also have to add "mask" line 459 :
else header.Cat((int)len); => else header.Cat((int)len | mask);
-your improvement ... no longer allows me to use "connect". Let me explain :
the server reject : "Get ws://serveur.example.com/chat/sensor-123 HTTP/1.1" // the complete adress
but accept : "Get /chat/sensor-123 HTTP/1.1" // sub adress
if followed by : "Host: server.example.com" // site adress
it is therefore essential to have acces to uri, which in some cases may be different from url.
For the Vector, I am not sure a "Standard header" exist. User should have to delete unwanted items, which is a more complex job than to build all the Header. May be a vectormap with some predefined key "Get", "Host", "Upgrade",Sec-WebSocket-Key" etc.. would facilate the use with "/r/n" taking in account of course.
A good idea should be to add the Websocket Protocol specification RF6455 example in the upp Websocket documentation, to help the user build his own header:
The handshake from the client looks as follows:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
JJ
|
|
|
|
|
|
Re: How to close the websocket connection [message #49574 is a reply to message #48944] |
Sun, 04 March 2018 15:51 |
uppjj
Messages: 9 Registered: February 2018 Location: France
|
Promising Member |
|
|
Ok thanks. This is working now with your new code, with url containing subfolder or not :
// adress
String Host,SubFolder;
bool ssl;
Adress_Split(Url,Host,SubFolder,ssl);
// header
WS_Client.ClearHeaders().Header("Upgrade","websocket").Header( "Connection","Upgrade").Header("Sec-WebSocket-Version", "13"); // may be standard part of header ?
WS_Client.Header("Sec-WebSocket-Protocol","your_protocol")...; // custom part
// connect
WS_Client.Connect(SubFolder,Host,ssl); // ok working now !
...
with :
void Adress_Split(const String& url,String& host,String& Subfolder,bool& ssl)
{// copy of the beginning of connect(url)
Subfolder = url;
const char *u = url;
ssl = memcmp(u, "wss", 3) == 0;
//--- Host
const char *t = u;
while(*t && *t != '?')
if(*t++ == '/' && *t == '/')
{
u = ++t;
break;
}
t = u;
while(*u && *u != ':' && *u != '/' && *u != '?')
u++;
host = String(t, u);
//--- SubFolder (JJ)
while(*u && *u != '/' && *u != '?') u++;
if (*u !=0) Subfolder = u;
}
|
|
|
Goto Forum:
Current Time: Fri Nov 01 01:08:15 CET 2024
Total time taken to generate the page: 0.02732 seconds
|
|
|