I have made a client that, when the windows firewall is OFF on the server then it will connect instantly to the server but when the firewall is ON then it takes around 30-35 secs to connect with server. I have tried adding firewall exceptions on server for my application and for ports as well but nothing is working out, its still taking the same amount of time.
here is my client piece of code where I am trying to connect with server :
bool connectSocket()
{
_connectSocket = socket(PF_INET, SOCK_STREAM,0);
if(_connectSocket == INVALID_SOCKET)
{
LOG_ERROR("Failed intiating socket with partner.");
return false;
}
struct sockaddr_in thataddr;
memset(&thataddr,0,sizeof(thataddr));
thataddr.sin_addr.s_addr = inet_addr(_partnerIP.c_str());
thataddr.sin_family = AF_INET;
thataddr.sin_port = htons(_partnerPort);
int i = ::connect(_connectSocket,(struct sockaddr *)&thataddr,sizeof(thataddr));
if(i<0)
{
//i = WSAGetLastError();
LOG_WARNING("Failed connecting to partner. Check partner status.");
return false;
}
}
When Firewall is ON on the server ::connect function will take 30-35 secs to give error.
Any help in this direction is highly appreciated.
Thanks
Related
I have a hardware that streams data to a windows server, and I have IP and port of this server. Now I want to connect unity app as a TCP client to this server. I have tried many solutions, but still have hard time to figure out best way to do this. Any help is highly appreciated. One issue that I have with current tutorials is that most of them define a unity server and try to connect another unity app as client and mostly based on localhost. However, I just want to connect a unity app as a TCP client to a server which I have IP and port.
Warm regards,
enter image description here
First of all, at the top of your script:
using System;
using System.Net.Sockets;
Then, create an instance of TcpClient and begin the connection:
socket = new TcpClient
{
// dataBufferSize is in bytes
ReceiveBufferSize = dataBufferSize,
SendBufferSize = dataBufferSize
};
socket.BeginConnect(ip, port, ConnectCallback, socket);
In ConnectCallback():
private void ConnectCallback(IAsyncResult asyncResult)
{
socket.EndConnect(asyncResult);
if (!socket.Connected) return;
// stream is a NetworkStream you should declare somewhere
stream = socket.GetStream();
// receiveBuffer is a byte[] you should declare somewhere
receiveBuffer = new byte[dataBufferSize];
stream.BeginRead(receiveBuffer, 0, dataBufferSize, ReceiveCallback, null);
}
In ReceiveCallback():
private void ReceiveCallback(IAsyncResult asyncResult)
{
try
{
int byteLength = stream.EndRead(asyncResult);
if (byteLength <= 0)
{
// Disconnect client
return;
}
// Transfer data from receiveBuffer to data variable for handling
byte[] data = new byte[byteLength];
Array.Copy(receiveBuffer, data, byteLength);
// Handle data in any way you want to
// BeginRead again so you can keep receiving data
stream.BeginRead(receiveBuffer, 0, dataBufferSize, ReceiveCallback, null);
}
catch (Exception e)
{
Console.WriteLine($"Error receiving TCP data: {e.Message}");
}
}
I got this information from this tutorial.
I'm trying to access a webserver after I've changed IP addresses on my ESP8266 arduino sketch, but it's not responding (but a ping is).
The sketch starts in WIFI_AP mode (for device testing purposes), but if a network is discovered after an asynchronous WiFi scan, the call back code disconnects the WiFi and then creates a connection in WIFI_AP_STA mode (acting as a secondary network access point).
ESP8266WebServer webServer(80);
void myWifiScanCompleted( int networksFound ) {
IPAddress ip(192,168,1,2); // fixed IP address of this access point
IPAddress gateway(192,168,1,254);
IPAddress subnet(255,255,255,0);
int count;
int quality;
networkConnection = NET_CONNECT_NONE; // initialise as not found
for(count = 0; count < networksFound; count++) {
quality = getRSSIasQuality( WiFi.RSSI(count) );
if(strcmp(WiFi.SSID(count).c_str(), ap_ssid ) == 0) {
debug_print("found network %s (%d\%)", ap_ssid, quality);
networkConnection = NET_CONNECT_FOUND;
break;
} else {
debug_print("ignoring network %s (%d\%)", WiFi.SSID(count).c_str(), quality);
}
}
if(networkConnection == NET_CONNECT_FOUND) { // found network = try to connect
// reset any existing connection
webServer.stop();
WiFi.disconnect();
delay(100);
WiFi.mode(WIFI_AP_STA); // need both modes to join the network to get IP address, and then create access point
WiFi.begin(ap_ssid, ap_password);
count = 0;
while (WiFi.status() != WL_CONNECTED) {
toggle_led(); // Blink the LED
if(++count > (15 * 10)) {
debug_print("error connecting to network %s", ap_ssid);
networkConnection = NET_CONNECT_NONE;
break; // failed to connect
}
delay(100);
}
if(networkConnection != NET_CONNECT_NONE) {
networkConnection = NET_CONNECT_CONNECTED; // we've successfully connected to the network, now set up the access point
ip = WiFi.localIP();
gateway = (uint32_t)0;
kev_softAPConfig(ip, gateway, subnet, false); // no DHCP server
if(! kev_softAP(ap_ssid, ap_password, MY_WIFI_CHANNEL, MY_WIFI_HIDDEN, MY_WIFI_MAX_CONNECTIONS)) {
debug_print("create %s softAP failed - performing network reset", ap_ssid);
WiFi.disconnect();
networkConnection = NET_CONNECT_NONE;
} else {
// access point started = restart server
webServer.begin(); // start web server on the new IP address
debug_print("create %s softAP OK", ap_ssid);
}
}
}
}
The functions kev_softAPConfig() and kev_softAP() are modified versions of the API that do NOT start the dhcp service (which already exists on the network).
I've proved these functions work, I've just changed the order of things so that I can provide device testing features.
Has anyone achieved this, or am I a pioneer? :-)
I found that I had to use a different IP range for the access point from the WiFi.localIP() allocated to the station by the network DHCP server, which meant having to write some proxy code to communicate across networks.
I have an application that sends a GET request using winsock on port 80 using a TCP socket. A few users have reported an issue where no response is received, looking at network logs and seeing the network device is getting the data just the app isn't it was clear that the firewall was blocking it.
Having disabled the firewall it then worked fine but what I don't understand is why it was getting blocked. The connection is created from the users computer, it connects fine and sends (which I assumes automatically opens a port) so how can data be lost on the same connection when received? Should I be providing additional winsock settings? Or is there simply no way around stopping the firewall blocking an already active connection?
Here is a stripped down version of the winsock code
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
return -1;
struct sockaddr_in client;
memset(&client, 0, sizeof(client));
client.sin_family = AF_INET;
client.sin_port = htons(80);
client.sin_addr.s_addr = inet_addr(inet_ntoa(*addr_list[0]));
if (connect(sock, (struct sockaddr *)&client, sizeof(client)) < 0){
closesocket(sock);
return -1;
}
if (send(sock, buffer, buflength, 0) != buflength){
closesocket(sock);
return -1;
}
//get response
response = "";
int resp_leng = BUFFERSIZE;
while (resp_leng == BUFFERSIZE)
{
resp_leng = recv(sock, (char*)&buffer, BUFFERSIZE, 0);
if (resp_leng > 0)
response += std::string(buffer).substr(0, resp_leng);
else
return -1;
}
closesocket(sock);
Your while loop exits if a recv() returns less than BUFFERSIZE. This is wrong -- you must always assume that recv() can return any amount of data from 1 byte up to and including the supplied buffer size.
I've been writing a server and every time I quit it and re-open it, it seems to fail to bind to the socket. I'm connecting 2 clients and then disconnecting them with close() before I shut down the server, I also then quit the clients before opening the server just in case, however it still seems to fail and I have to restart my computer. Here is my code:
listenSocket = device = app = 0;
struct sockaddr_in server_addr;
char buffer[1024];
listenSocket = socket(AF_INET, SOCK_STREAM, 0);
memset(&server_addr, '0', sizeof(server_addr));
memset(buffer, '0', sizeof(buffer));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(35565);
//bind the socket
if (bind(listenSocket,(struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
NSLog(#"Error binding to socket");
}
if (listen(listenSocket, 5) == -1) {
NSLog(#"Failed to listen");
}
//launch thread for console
[NSThread detachNewThreadSelector:#selector(console) toTarget:self withObject:nil];
NSLog(#"Starting server");
//socket open, ask for clients
while (true) {
int client = -1;
if (!device || !app)
client = accept(listenSocket, (struct sockaddr*)NULL, NULL);
//handshake omitted for length
}
And the code to close the server:
close(listenSocket);
close(device);
close(app);
NSLog(#"Clean");
Is there something I'm doing wrong? Any help would be appreciated. Thanks.
EDIT: Here is my error checking code:
NSLog(#"%s",strerror(errno));
int e = bind(listenSocket,(struct sockaddr*)&server_addr, sizeof(server_addr));
NSLog(#"%s",strerror(errno));
You need to set the SO_REUSEADDR option. Otherwise, once you grab the port in a process, there is a significant timeout before the kernel will let you have it again. Much detail to be found in an existing question; I've voted to close as a duplicate.
I had a similar problem which was caused by another process holding on to the ports. Killing that process solved the problem.
I need to setup an ethernet (web) server that have to be turned on and off depending on some conditions on the Arduino UNO.
I read the docs of the Server class in the Ethernet library and it seems there is no chance to stop the server once you started, i.e. there is no EthernetServer.begin() counterpart.
I thought then to setup the server in the setup section and serve incoming connections depending on when the given condition:
EthernetServer server = EthernetServer(80);
void setup() {
Ethernet.begin(mac, ip);
server.begin();
}
void loop() {
if (condition) {
EthernetClient client = server.available();
if (client == true) {
// serve the client...
}
} else {
// do something else
}
}
This indeed works, but the client is not properly rejected: it is just leaved pending. In the browser one can see the web page loading idefinitely, and if the condition turns to true the client will eventually be served for the request issued when the condition was false.
I see no methods for rejecting the request (there is no counterpart of EthernetServer.available()). The only thing that comes to my mind is to perform a
server.available().stop();
in the beginning of the else block. This prevent to serve requests issued while the condition was false, but doesn't prevent the connection between the client and the server to take place (it's like opening a connection and shut it down immediately).
How could I avoid to establish connections at all while the condition is false?
I'm guessing here since I don't have my Arduino collection handy, but from memory and reading the reference you could try something like
void loop()
{
EthernetClient client = server.available();
if ( !condition )
{
client.stop(); // break connection and do something else
}
else
{
// serve the client...
}
}
Hope that may at least help you in the right direction.
Cheers,
Could you just return a 404 header when you want the server disabled?
if(!condition)
{
client.println("HTTP/1.1 404 OK");
client.println("Content-Type: text/html");
client.println("Connnection: close");
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html><body>404</body></html>");
}
else
{
// serve client
}
I am writing this answer here as it is the only post still active or that hasn't been closed regarding this topic. Despite countless researches regarding being able to switch the EthernetServer on or off at will, this is not possible. The only thing you can do is use some functions defined "public" in the classes of the Ethernet/W5100/W5200/W5500 libraries.
The features I've noticed that actually impact the reliability of the network card are:
#include <Ethernet.h>
#include <utility/w5100.h>
W5100.setRetransmissionTime(milliseconds);
W5100.setRetransmissionCount(number);
(helps to shorten waiting times in case of Wiznet W5100/W5200/W5500 network card timeout)
EthernetClient::setConnectionTimeout(CONNECTION_TIMEOUT);
EthernetClient::setTimeout(CONNECTION_INPUT_STREAMING_TIMEOUT);
(they help to shorten waiting times in case of timeout of the client connected to the EthernetServer)
More tips:
when EthernetServer::available() returns false consider using EthernetServer::flush() to flush server buffers;
when using EthernetClient::write() also use EthernetClient::flush() to ensure that all data has been sent;
use EthernetClient::close() on dead/useless clients to free sockets easely.
Consider implementing a function to force-close network sockets, using the following code:
#include <SPI.h>
#include <utility/w5100.h>
void closeAllSockets()
{
for (int i = 0; i < MAX_SOCK_NUM; i++)
{
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
W5100.execCmdSn(i, Sock_CLOSE);
SPI.endTransaction();
}
}
void printAllSockets()
{
for (int i = 0; i < MAX_SOCK_NUM; i++)
{
Serial.print(F("Socket #"));
Serial.print(i);
uint8_ts = W5100.readSnSR(i);
Serial.print(F(": 0x"));
Serial.print(s, 16);
Serial.print(F(" "));
Serial.print(W5100.readSnPORT(i));
Serial.print(F(" D:"));
uint8_t dip[4];
W5100.readSnDIPR(i, dip);
for (int j = 0; j < 4; j++)
{
Serial.print(dip[j], 10);
if (j < 3)
Serial.print(".");
}
Serial.print(F("("));
Serial.print(W5100.readSnDPORT(i));
Serial.println(F(")"));
}
}
MAX_SOCK_NUM changes according to the network card, the Wiznet W5100 has a maximum of 4 sockets, the W5200 and W5500 has a maximum of 8 sockets.
Hope this helps someone.