I trying to interface ethernet module with esp32.My connections are as follows:
SO--> MOSI pin 23 SI--> MISO pin 19 CS--> CS pin 5 SCK-->CLK pin18
output data is:
rst:0x1 (POWERON_RESET),boot:0x13
(SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2 load:0x3fff0018,len:4 load:0x3fff001c,len:1044
load:0x40078000,len:10124 load:0x40080400,len:5828 entry 0x400806a8
Local IP : 0.0.0.0 Subnet Mask : 0.0.0.0 Gateway IP : 0.0.0.0 DNS
Server : 0.0.0.0 Ethernet Successfully Initialized
I cant able to connect to ethernet I don't know how to over come this.
#include <utility/logging.h>
EthernetClient ethClient;
uint8_t macaddress[6] = {0x1,0x2,0x3,0x4,0x5,0x6};
void setup() {
Serial.begin(115200);
//Ethernet.init(5);
Ethernet.begin(macaddress); // Dynamic IP setup
delay(5000);
Serial.print("Local IP : ");
Serial.println(Ethernet.localIP());
Serial.print("Subnet Mask : ");
Serial.println(Ethernet.subnetMask());
Serial.print("Gateway IP : ");
Serial.println(Ethernet.gatewayIP());
Serial.print("DNS Server : ");
Serial.println(Ethernet.dnsServerIP());
Serial.println("Ethernet Successfully Initialized");
}
void loop()
{
}
Related
I'm having a problem using both TCP and UDP in the same sketch. What appears to happen is that if the same socket is reused for UDP after it was in use for TCP, UPD fails to receive data. I was able to reproduce this with the WebServer example. I've added to it a DNS query once in every 10 seconds to query yahoo.com IP address. The DSN queries succeed if I'm not creating any client traffic from the browser. After I query the server over HTTP over TCP, the DSN queries start to fail. DNS queries are implemented in UDP. This is the code that I'm using:
/*
Web Server
A simple web server that shows the value of the analog input pins.
using an Arduino Wiznet Ethernet shield.
Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
* Analog inputs attached to pins A0 through A5 (optional)
created 18 Dec 2009
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
modified 02 Sept 2015
by Arturo Guadalupi
*/
#include <SPI.h>
#include <Ethernet.h>
#include <Dns.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 1, 177);
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
unsigned long t0;
void setup() {
// You can use Ethernet.init(pin) to configure the CS pin
//Ethernet.init(10); // Most Arduino shields
//Ethernet.init(5); // MKR ETH shield
//Ethernet.init(0); // Teensy 2.0
//Ethernet.init(20); // Teensy++ 2.0
//Ethernet.init(15); // ESP8266 with Adafruit Featherwing Ethernet
//Ethernet.init(33); // ESP32 with Adafruit Featherwing Ethernet
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Ethernet WebServer Example");
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
// start the server
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
t0 = millis();
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 5"); // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);
client.println("<br />");
}
client.println("</html>");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
} else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disconnected");
}
if (millis() - t0 > 10000)
{
DNSClient dns;
dns.begin(IPAddress(8,8,8,8));
IPAddress yahoo;
if (dns.getHostByName("yahoo.com", yahoo) == 1)
{
Serial.print("Yahoo: ");
Serial.print(yahoo[0]);
Serial.print(".");
Serial.print(yahoo[1]);
Serial.print(".");
Serial.print(yahoo[2]);
Serial.print(".");
Serial.println(yahoo[3]);
}
else
{
Serial.println("Failed to query yahoo.com IP address");
}
t0 = millis();
}
}
Is this a known issue? Can someone please help in identifying the problem in my code, or if there is a workaround for this issue? Can it be a hardware issue? I'm using SunFounder boards, not the original Arduino boards.
Thanks a lot,
Boaz,
I am trying to establish an IPV6 socket connection with net-core 3.0 on a linux-arm platform (raspberry pi).
At the time when I try to bind the socket to the local ethernet adapter an Exception ((22): Invalid argument [fe80::211c:bf90:fbbf:9800]:5400) is thrown.
When i try the same on my windows development machine (with a different link-local ip), everything works fine.
IPV4 socket connection is also possible on both, my windows development machine and on the target linux-arm platform.
To the source code:
I used the socket example of microsoft as a base and changed the IPV4 into an IPV6 address.
The exception is thrown after the "Bind" method.
Here is the client side code:
//definet the target endpoint
IPAddress ipAddress;
IPAddress.TryParse("fe80::211c:bf90:fbbf:9800", out ipAddress);
IPEndPoint remoteEP = new IPEndPoint(ipAddress, 5400);
// Create a TCP/IP socket.
Socket sender = new Socket(ipAddress.AddressFamily ,SocketType.Stream, ProtocolType.Tcp);
//bind to the local network interface
IPAddress localIp;
IPAddress.TryParse("fe80::833:e68b:32ee:4c39", out localIp);
EndPoint localEndPoint = new IPEndPoint(IPAddress.IPv6Any, 0);
sender.Bind(localEndPoint);
// Connect the socket to the remote endpoint. Catch any errors.
try
{
sender.Connect(remoteEP);
Console.WriteLine("Socket connected to {0}",
sender.RemoteEndPoint.ToString());
The input of Ron was in fact the missing part. Hence the target endpoint IpAddress has to provided with the ScopeId (NIC Nr).
//definet the target endpoint
IPAddress ipAddress;
IPAddress.TryParse("fe80::211c:bf90:fbbf:9800", out ipAddress);
ipAddress.ScopeId = scopeId;
IPEndPoint remoteEP = new IPEndPoint(ipAddress, 5400);
To the scope ID of the first link local address for example this code can be used:
private static long GetScopeIdForHostLinkLocal()
{
IPAddress firstLinkLocal = null;
var info = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface nic in info)
{
var ipProps = nic.GetIPProperties();
var uniAddresses = ipProps.UnicastAddresses;
foreach (UnicastIPAddressInformation addressInfo in uniAddresses)
{
if (addressInfo.Address.IsIPv6LinkLocal)
{
firstLinkLocal = addressInfo.Address;
break;
}
}
if (firstLinkLocal != null)
{
break;
}
}
if (firstLinkLocal != null)
{
return firstLinkLocal.ScopeId;
}
else
{
return -1;
}
}
I'm struggling to make sense of this. The issue is seen on a machine that is:
Remote (I do not have access to it)
Running Windows 7
NOT running a proxy or VPN (or so I have been told)
My application has a snippet of code that tries to quickly determine which interface the OS prefers. It does the following:
// Create a socket
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
// Resolve DNS query
DWORD dwRemoteIp = GetHostAddr("www.google.com")
// I've simplified the call here, but "www.google.com" resolves to 172.217.3.100 in host byte order, so the resolution is correct
// Create the remote address to connect to
sockaddr_in remoteaddr = {0};
remoteaddr.sin_family = AF_INET;
remoteaddr.sin_addr.s_addr = htonl(dwRemoteIp);
remoteaddr.sin_port = htons(80);
// Connect the socket
if (0 == connect(sock, (struct sockaddr*)&remoteaddr, sizeof(remoteaddr))) {
// The connection succeeded -- see which local address was bound to
sockaddr_in localaddr = {0};
int len = sizeof(localaddr);
if (0 == getsockname(sock, (struct sockaddr*)&localaddr, (socklen_t *)&len)) {
// Here is where I see dwLocalIp == 0x7F000001, or 127.0.0.1
DWORD dwLocalIp = ntohl(localaddr.sin_addr.s_addr);
}
}
What could be going on here?
I created a TCP server program which binds, listen and accepting a connection from the specific ip address and port number.
During the first connection : Server is accepting a SYN packet from the client and sending an ACK back to the client. Later getting a ACK from the client. Finally Client is RST with the server.
During the second connection the client is sending a SYN packet to the slave but there is no ACK from the server.
I think there is no binding is possible during the second connection with the same ip address and port number.
Is it possible to bind with the SAME ip address and port number in the second connection ?
server :
SOCKET sock;
SOCKET fd;
uint16 port = 52428;
// I am also using non blocking mode
void CreateSocket()
{
struct sockaddr_in server, client; // creating a socket address structure: structure contains ip address and port number
WORD wVersionRequested;
WSADATA wsaData;
int len;
int iResult;
u_long iMode = 1;
printf("Initializing Winsock\n");
wVersionRequested = MAKEWORD (1, 1);
iResult = WSAStartup (wVersionRequested, &wsaData);
if (iResult != NO_ERROR)
printf("Error at WSAStartup()\n");
// create socket
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
printf("Could not Create Socket\n");
//return 0;
}
printf("Socket Created\n");
iResult = ioctlsocket(sock, FIONBIO, &iMode);
if (iResult < 0)
printf("\n ioctl failed \n");
// create socket address of the server
memset( &server, 0, sizeof(server));
// IPv4 - connection
server.sin_family = AF_INET;
// accept connections from any ip adress
server.sin_addr.s_addr = htonl(INADDR_ANY);
// set port
server.sin_port = htons(52428);
//Binding between the socket and ip address
if(bind (sock, (struct sockaddr *)&server, sizeof(server)) < 0)
{
printf("Bind failed with error code: %d", WSAGetLastError());
}
//Listen to incoming connections
if(listen(sock, 10) == -1){
printf("Listen failed with error code: %d", WSAGetLastError());
}
printf("Server has been successfully set up - Waiting for incoming connections");
for(;;){
len = sizeof(client);
fd = accept(sock, (struct sockaddr*) &client, &len);
if (fd < 0){
printf("Accept failed");
closesocket(sock);
}
//echo(fd);
printf("\n Process incoming connection from (%s , %d)", inet_ntoa(client.sin_addr),ntohs(client.sin_port));
//closesocket(fd);
}
}
TCP connections are identified by four parameters:
Local IP
Local port
Remote IP
Remote port
The server normally uses the same Local IP and port for all its connections (e.g. an HTTP server listens on port 80 for all connection). Each connection from a client will have a different Remote IP and/or Remote port, and these resolve the ambiguity.
When the server closes all of its connected sockets, the TCB sticks around for several minutes in a TIME_WAIT state. This normally prevents a process from binding to the port, because you can't bind to a local IP/port that has any associated TCBs. If you want to restart the server and bind to the same port and address that it just used for connections, you need to use the SO_REUSEADDR socket option to get around this. See:
Socket options SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do they mean the same across all major operating systems?
for details of this.
This is a continuation of Connecting IPv4 client to IPv6 server: connection refused. I am experimenting with dual stack sockets and trying to understand what setsockopt with IPV6_V6ONLY is useful for. On the linked question I was advised that "Setting IPV6_V6ONLY to 0 can be useful if you also bind the server to an IPv6-mapped IPv4 address". I have done this below, and was expecting my server to be able to accept connections from both an IPv6 and an IPv4 client. But shockingly when I run my client with a V4 and a V6 socket, neither can connect!
Can someone please tell me what I am doing wrong, or have I misunderstood IPv6 dual stack functionality all together?
Server:
void ConvertToV4MappedAddressIfNeeded(PSOCKADDR pAddr)
{
// if v4 address, convert to v4 mapped v6 address
if (AF_INET == pAddr->sa_family)
{
IN_ADDR In4addr;
SCOPE_ID scope = INETADDR_SCOPE_ID(pAddr);
USHORT port = INETADDR_PORT(pAddr);
In4addr = *(IN_ADDR*)INETADDR_ADDRESS(pAddr);
ZeroMemory(pAddr, sizeof(SOCKADDR_STORAGE));
IN6ADDR_SETV4MAPPED(
(PSOCKADDR_IN6)pAddr,
&In4addr,
scope,
port
);
}
}
addrinfo* result, hints;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
int nRet = getaddrinfo("powerhouse", "82", &hints, &result);
SOCKET sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
int no = 0;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&no, sizeof(no)) != 0)
return -1;
ConvertToV4MappedAddressIfNeeded(result->ai_addr);
if (bind(sock, result->ai_addr, 28/*result->ai_addrlen*/) == SOCKET_ERROR)
return -1;
if (listen(sock, SOMAXCONN) == SOCKET_ERROR)
return -1;
SOCKET sockClient = accept(sock, NULL, NULL);
printf("Got one!\n");
Client:
addrinfo* result, *pCurrent, hints;
char szIPAddress[INET6_ADDRSTRLEN];
memset(&hints, 0, sizeof hints); // Must do this!
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
const char* pszPort = "82";
if (getaddrinfo("powerhouse", "82", &hints, &result) != 0)
return -1;
SOCKET sock = socket(AF_INET, result->ai_socktype, result->ai_protocol);
int nRet = connect(sock, result->ai_addr, result->ai_addrlen);
My C skills are a bit rusty, so here is a counter-example written in Python. My local IPv4 address is 37.77.56.75, so that is what I will bind to. I kept it as simple as possible to focus on the concepts.
This is the server side:
#!/usr/bin/env python
import socket
# We bind to an IPv6 address, which contains an IPv6-mapped-IPv4-address,
# port 5000 and we leave the flowinfo (an ID that identifies a flow, not used
# a lot) and the scope-id (basically the interface, necessary if using
# link-local addresses)
host = '::ffff:37.77.56.75'
port = 5000
flowinfo = 0
scopeid = 0
sockaddr = (host, port, flowinfo, scopeid)
# Create an IPv6 socket, set IPV6_V6ONLY=0 and bind to the mapped address
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM, 0)
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
sock.bind(sockaddr)
# Listen and accept a connection
sock.listen(0)
conn = sock.accept()
# Print the remote address
print conn[1]
Here we bind to an IPv6 address in the code, but the address is actually an IPv6-mapped IPv4 address, so in reality we are binding to an IPv4 address. This can be seen when looking at i.e. netstat:
$ netstat -an | fgrep 5000
tcp4 0 0 37.77.56.75.5000 *.* LISTEN
We can then use an IPv4 client to connect to this server:
#!/usr/bin/env python
import socket
# Connect to an IPv4 address on port 5000
host = '37.77.56.75'
port = 5000
sockaddr = (host, port)
# Create an IPv4 socket and connect
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
conn = sock.connect(sockaddr)
And the server will show us who connected, using IPv6 address representation:
('::ffff:37.77.56.76', 50887, 0, 0)
In this example I connected from IPv4 host 37.77.56.76, and it choose port 50887 to connect from.
In this example we are only listening on an IPv4 address (using IPv6 sockets, but it is still an IPv4 address) so IPv6-only clients will not be able to connect. A client with both IPv4 and IPv6 could of course use IPv6 sockets with IPv6-mapped-IPv4-addresses, but then it would not really be using IPv6, just an IPv6 representation of an IPv4 connection.
A dual-stack server has to either:
listen on the wildcard address, which will make the OS accept connections on any address (both IPv4 and IPv6)
listen on both an IPv6 address and an IPv4 address (either by creating an IPv4 socket, or by creating an IPv6 socket and listening to an IPv6-mapped-IPv4-address as shown above)
Using the wildcard address is the most simple. Just use the server example from above and replace the hostname:
# We bind to the wildcard IPv6 address, which will make the OS listen on both
# IPv4 and IPv6
host = '::'
port = 5000
flowinfo = 0
scopeid = 0
sockaddr = (host, port, flowinfo, scopeid)
My Mac OS X box shows this as:
$ netstat -an | fgrep 5000
tcp46 0 0 *.5000 *.* LISTEN
Notice the tcp46 which indicates that it listens on both address families. Unfortunately on Linux it only shows tcp6, even when listening on both families.
Now for the most complicated example: listening on multiple sockets.
#!/usr/bin/env python
import select
import socket
# We bind to an IPv6 address, which contains an IPv6-mapped-IPv4-address
sockaddr1 = ('::ffff:37.77.56.75', 5001, 0, 0)
sock1 = socket.socket(socket.AF_INET6, socket.SOCK_STREAM, 0)
sock1.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
sock1.bind(sockaddr1)
sock1.listen(0)
# And we bind to a real IPv6 address
sockaddr2 = ('2a00:8640:1::224:36ff:feef:1d89', 5001, 0, 0)
sock2 = socket.socket(socket.AF_INET6, socket.SOCK_STREAM, 0)
sock2.bind(sockaddr2)
sock2.listen(0)
# Select sockets that become active
sockets = [sock1, sock2]
readable, writable, exceptional = select.select(sockets, [], sockets)
for sock in readable:
# Accept the connection
conn = sock.accept()
# Print the remote address
print conn[1]
When running this example both sockets are visible:
$ netstat -an | fgrep 5000
tcp6 0 0 2a00:8640:1::224.5000 *.* LISTEN
tcp4 0 0 37.77.56.75.5000 *.* LISTEN
And now IPv6-only clients can connect to 2a00:8640:1::224:36ff:feef:1d89 and IPv4-only clients can connect to 37.77.56.75. Dual stack clients can choose which protocol they want to use.