asynchronous client socket closing? - sockets

hey i want to ask a question about asynchronous socket communication on c#. everything is working well for now apart from closing clients. server doesnot close immediately the worker socket for client when a client close its conneciton. it closes a few time later. how can i resolve this problem??

check this link http://msdn.microsoft.com/en-us/library/fx6588te.aspx#2 my problem is that I can't keep the connection open after I receive a message from the client.
If I do as said on that sample the connection is closed immediately after receiving the message.
If I don't close the connection I can only receive one message and nothing more.
If you have any solution to this throw it this way.
I got it!
If anybody else has this problem they should do the following.
Change this code:
content = state.sb.ToString()
to this:
content = state.sb.ToString().TrimEnd(New Char() {ChrW(13)})
then you should change this:
If content.IndexOf("<EOF>") > -1 Then
to this:
If content.IndexOf(New Char() {ChrW(13)}) > -1 Then
this will receive Enter (chrw(13)) as the end of line.
then here:
Console.WriteLine("Read {0} bytes from socket. " + vbLf + " Data : {1}", content.Length, content)
' Echo the data back to the client.
Send(handler, content)
you should do this:
Console.WriteLine("Read {0} bytes from socket. " + vbLf + " Data : {1}", content.Length, mid(content,1,content.length -2))
' Echo the data back to the client.
'Send(handler, content)
content = String.Empty
state.sb.Clear()
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReadCallback), state)
And your done.

Related

POST request on arduino with ESP8266 using WifiESP library

I am attempting to make RESTful POST request using the WifiESP library (https://github.com/bportaluri/WiFiEsp). I'm able to successfully make the request with curl, but consistently get an error using the Arduino and ESP. I suspect the problem is related to the manual formatting of the POST request the library requires, but I don't see anything wrong. Here my sanitized code:
if (client.connect(server, 80)) {
Serial.println("Connected to server");
// Make a HTTP request
String content = "{'JSON_key': 2.5}"; // some arbitrary JSON
client.println("POST /some/uri HTTP/1.1");
client.println("Host: http://things.ubidots.com");
client.println("Accept: */*");
client.println("Content-Length: " + sizeof(content));
client.println("Content-Type: application/json");
client.println();
client.println(content);
}
The error I get (via serial monitor) is this:
Connected to server
[WiFiEsp] Data packet send error (2)
[WiFiEsp] Failed to write to socket 3
[WiFiEsp] Disconnecting 3
My successful curl requests looks like this:
curl -X POST -H "Content-Type: application/json" -d 'Some JSON' http://things.ubidots.com/some/uri
After some experimentation, here is the solution to the multiple problems.
The JSON object was not correctly formatted. Single quotes were not accepted, so I needed to escape the double quotes.
The host does not need "http://" in a POST request; POST is a HTTP method.
The sizeof() method returns the size, in bytes, of the variable in memory rather than the length of the string. It needs to be replaced by .length().
Appending an integer to a string requires a cast.
This is the corrected code:
if (client.connect(server, 80)) {
Serial.println("Connected to server");
// Make the HTTP request
int value = 2.5; // an arbitrary value for testing
String content = "{\"JSON_key\": " + String(value) + "}";
client.println("POST /some/uri HTTP/1.1");
client.println("Host: things.ubidots.com");
client.println("Accept: */*");
client.println("Content-Length: " + String(content.length()));
client.println("Content-Type: application/json");
client.println();
client.println(content);
}
The code explained by Troy D is right and it's working .I think the error in posting the data to the server is due to this line
client.println("Content-Length: " + sizeof(content));
and the correct way is
client.println("Content-Length: " + String(content.length()));
Now coming to this error
Connected to server
[WiFiEsp] Data packet send error (2)
[WiFiEsp] Failed to write to socket 3
[WiFiEsp] Disconnecting 3
This is the error of library you can ignore it.
The problem with "Data packet send error (2)", "Failed to write to socket 3" and "Disconnecting 3" is not a problem within the WifiEsp library as far as I can see, believe it's more likely to be within the AT firmware. By default the http headers contain a "Connection: close" parameter which in normal cases should be correct. However with this bug the server will get disconnected before the reply is received on the client side and any response from the server will be identified as garbage data. Using the value "Connection: keep-alive" as a workaround will make it possible to receive the acceptance from the server in a proper way.
I'm running my Arduino + ESP8266-07 against a MVC based Web Api that I created on one of my servers and in the controllers Post-method I use a single string as return value, the value I return if everything is ok is simply one of the strings that WifiEsp keeps track of (It will still include the http status code in the response header that it returns)
public async Task<string> Post([FromBody]JObject payload)
{
//Code to handle the data received, in my case I log unit ip, macaddress, datetime and sensordata into a db with entity framework
return "SEND OK";
}
So in your Arduino code try following instead:
String PostHeader = "POST http://" + server + ":" + String(port) + "/api/values HTTP/1.1\r\n";
PostHeader += "Connection: keep-alive\r\n";
PostHeader += "Content-Type: application/json; charset=utf-8\r\n";
PostHeader += "Host: " + server + ":" + String(port) + "\r\n";
PostHeader += "Content-Length: " + String(jsonString.length()) + "\r\n\r\n";
PostHeader += jsonString;
client.connect(server.c_str(), port);
client.println(PostHeader);
client.stop();
In the file debug.h located in the library source code you could alter a define and get more output to your serial console. Open the file and change
#define _ESPLOGLEVEL_ 3
to
#define _ESPLOGLEVEL_ 4
Save the file and recompile/deploy your source code to your Arduino and you will get extensive information about all AT commands the library sends and what the library receives in return.

ESP8266: How to send TCP messages using AT+CIPSEND command

I am experimenting with Arduino and ESP8266 module, and now I am trying to send some sensor data to a TCP server. For this purposes I am using AT+CIPSTART command (to establish a TCP connection) and AT+CIPSEND to send the data.
If I am testing it using Serial Monitor, it works fine. After entering CIPSEND command I can write some text in a terminal and this message/text will be sent to the TCP server.
When I am trying to make it inside Arduino sketch, then it sends an empty message. The connection works, but I do not see any data.
How can I send a message text (msg) with my TCP packet?
Here is a code snippet
// ESP8266 Client
String cmd = "AT+CIPSTART=\"TCP\",\"";// Setup TCP connection
cmd += IP;
cmd += "\",3103";
sendDebug(cmd);
delay(2000);
if( Serial.find( "Error" ) )
{
debug.print( "RECEIVED: Error\nExit1" );
return;
}
String msg = "test";
Serial.print( "AT+CIPSEND=" );
Serial.println( msg.length() );
if(Serial.find( ">" ) )
{
debug.print(">");
debug.print(msg);
Serial.print(msg);
}
else
{
sendDebug( "AT+CIPCLOSE" );//close TCP connection
}
if( Serial.find("OK") )
{
debug.println( "RECEIVED: OK" );
}
else
{
debug.println( "RECEIVED: Error\nExit2" );
}
}
First of all, Select how much character or byte is needed to transmit. It is better to use softwareSerial library to connect with ESP8266 and send AT commands.
Suppose yow want to send 5 bytes.Type the following AT commands and must give a delay more than 100 millisecond before sending data. Here "\r" is carriage return and "\n" is new line. After including this, ESP8266 can understand you have ended the command.
esp.print("AT+CIPSEND=5\r\n");
delay(1000);
esp.print("Hello");
Your code is not working because you are using unvarnished transmission mode. So to complete a packet you need to transmit 2048 bytes which you are not writing.

How to HTTP POST in Lua without using Lua Socket

I am trying to send a HTTP POST command to an external server from a Lua scripted piece of hardware. In order to do so I have to create a tcpConnection and then do a tcpSend() command. I have confirmed the TCP Connection using wireshark and I have seen it send the HTTP GET command but I do not know how to send a post. I have tried to just change the GET to POST in the code but no avail.
debugConsole = -20
while true do
--Opening connection to remote host
debugConsole = tcpConnect("192.168.1.1", 80, 100)
print("TCP connect " .. debugConsole)
debugConsole = tcpSend("GET /api/v1/profiles/active_profiles.json?profile=5&expiry=1&duration=0&auth_token=2e608b72390a866f4bc7bbb6db63a1aa HTTP/1.1 \r\n\r\n")
print("TCP Send = " .. debugConsole)
--Printing response from remote host
print(responseSubstr(0, 500))
debugConsole = tcpClose()
print("TCP Close = " .. debugConsole)
debugConsole = httpRequest("http://192.168.1.1/api/v1/profiles/active_profiles.json?profile=5&expiry=1&duration=0&auth_token=2e608b72390a866f4bc7bbb6db63a1aa", 10)
print("HTTP Request = " .. debugConsole)
print(" ")
sleep (10000)
end

read / write on socket descriptors linux c

I am trying to send the contents of a file from the server to the client , I am reading the file line by line using fgets and writing to the socket descriptor line by line , on the client side , i am in an a while loop , reading the sent contents.I am not being able to terminate the server sending sequence , i.e the client keeps reading the buffer and the next program line is not executed , I think thers something wrong with my way of sending or recieving . here is the code :
server :
filefd = fopen("clients.txt","a+");
while(fgets(filcont,300,filefd) != NULL)
{// write whole file contents to client
n=write(newsockfd,filcont,strlen(filcont));
if(n==0) break;
memset(filcont,'\0',300);
}
fclose(filefd);
client side :
while(n>0){
n = read(sockfd,buffer,sizeof(buffer)-1);
if(n==0) break;
printf("%s\nbytes read :%d \n",buffer,n);
memset(buffer,'\0',256);
}
printf("Enter peer name ( except yours ) to send connection request : \n");
the above line ( printf , peer name doesnot get executed until i terminate the server)
I was able to figure it out , I sent the file contents from the server using fread instead of fgets ( line by line ) and used a single read() at the client . this was the quick fix.
But I also figured out another technique when in case you have to compulsorily use fgets , where the while loop at the client side makes the socket nonblocking for read and then blocking again , the code is pasted below.
flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
while(n>0){
n = read(sockfd,buffer,sizeof(buffer)-1);
if(n==0) break;
if(n==-1) printf("\nNon blocking read failed congrats");
printf("%s\n",buffer);
memset(buffer,'\0',256);
}
printf("\nbytes read :%d \n",n);
val = fcntl(sockfd, F_GETFL, 0);
flags = O_NONBLOCK;
val &= ~flags; // makes it blocking again
fcntl(sockfd,F_SETFL,val);
The code from stackoverflow was refered to make the socket blocking

stream_socket_server: Client browser randomly aborting?

Below is partial code to an experimental http server app I'm building from scratch from a PHP CLI script (Why? Because I have too much time on my hands). The example below more closely matches PHP's manual page on this function. The problem I'm getting is when connecting to this server app via a browser (Firefox or IE8 from two separate systems tested so far), the browser sends an empty request payload to the server and aborts roughly every 1 in 6 page loads.
The server console displays the "Connected with [client info]" each time. However, about 1 in 6 connections will result in a "Client request is empty" error. No error is given telling the header/body response write to the socket failed. The browser will generally continue to read what I give it, but this isn't usable as I can't fulfill the client's intended request without knowing what it is.
<?php
$s_socket_uri = 'tcp://localhost:80';
// establish the server on the above socket
$s_socket = stream_socket_server($s_socket_uri, $errno, $errstr, 30) OR
trigger_error("Failed to create socket: $s_socket_uri, Err($errno) $errstr", E_USER_ERROR);
$s_name = stream_socket_get_name($s_socket, false) OR
trigger_error("Server established, yet has no name. Fail!", E_USER_ERROR);
if (!$s_socket || !$s_name) {return false;}
/*
Wait for connections, handle one client request at a time
Though to not clog up the tubes, maybe a process fork is
needed to handle each connection?
*/
while($conn = stream_socket_accept($s_socket, 60, $peer)) {
stream_set_blocking($conn, 0);
// Get the client's request headers, and all POSTed values if any
echo "Connected with $peer. Request info...\n";
$client_request = stream_get_contents($conn);
if (!$client_request) {
trigger_error("Client request is empty!");
}
echo $client_request."\n\n"; // just for debugging
/*
<Insert request handling and logging code here>
*/
// Build headers to send to client
$send_headers = "HTTP/1.0 200 OK\n"
."Server: mine\n"
."Content-Type: text/html\n"
."\n";
// Build the page for client view
$send_body = "<h1>hello world</h1>";
// Make sure the communication is still active
if ((int) fwrite($conn, $send_headers . $send_body) < 1) {
trigger_error("Write to socket failed!");
}
// Response headers and body sent, time to end this connection
stream_socket_shutdown($conn, STREAM_SHUT_WR);
}
?>
Any solution to bring down the number of unintended aborts down to 0, or any method to get more stable communication going? Is this solvable on my server's end, or just typical browser behavior?
I tested your code and it seems I got better results reading the socket with fread(). You also forgot the main loop(while(1), while(true) or for(;;).
Modifications to your code:
stream_socket_accept with #stream_socket_accept [sometimes you get warnings because "the connected party did not properly respond", which is, of course, the timeout of stream_socket_accept()]
Added the big while(1) { } loop
Changed the reading from the socket from $client_request = stream_get_contents($conn);
to while( !preg_match('/\r?\n\r?\n/', $client_request) ) { $client_request .= fread($conn, 1024); }
Check the source code below (I used 8080 port because I already had an Apache listening on 80):
<?php
$s_socket_uri = 'tcp://localhost:8080';
$s_socket = stream_socket_server($s_socket_uri, $errno, $errstr, 30) OR
trigger_error("Failed to create socket: $s_socket_uri, Err($errno) $errstr", E_USER_ERROR);
$s_name = stream_socket_get_name($s_socket, false) OR
trigger_error("Server established, yet has no name. Fail!", E_USER_ERROR);
if (!$s_socket || !$s_name) {return false;}
while(1)
{
while($conn = #stream_socket_accept($s_socket, 60, $peer))
{
stream_set_blocking($conn, 0);
echo "Connected with $peer. Request info...\n";
// $client_request = stream_get_contents($conn);
$client_request = "";
// Read until double \r
while( !preg_match('/\r?\n\r?\n/', $client_request) )
{
$client_request .= fread($conn, 1024);
}
if (!$client_request)
{
trigger_error("Client request is empty!");
}
echo $client_request."\n\n";
$headers = "HTTP/1.0 200 OK\n"
."Server: mine\n"
."Content-Type: text/html\n"
."\n";
$body = "<h1>hello world</h1><br><br>".$client_request;
if ((int) fwrite($conn, $headers . $body) < 1) {
trigger_error("Write to socket failed!");
}
stream_socket_shutdown($conn, STREAM_SHUT_WR);
}
}
Add sleep(1) after stream_set_blocking