Pages: 1 2 [3]   Go Down
Author Topic: Ethernet data transfer stalling or failing  (Read 9022 times)
0 Members and 1 Guest are viewing this topic.
Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 140
Posts: 5873
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

... and you disabled the SD SPI interface on digital pin 4? Just checking. There have been more than a few posts here.

You are either getting interference on the ethernet connection, or the SPI interface. That is the only two interfaces you are using.

"Still connected" and "Done reading for now" back-to-back means the server is not finished sending packets. It just did not receive a new packet during that check.
Logged

SF Bay area
Offline Offline
Sr. Member
****
Karma: 2
Posts: 266
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

regardless if the socket recv returned 0 or -1, EthernetClient read forces it to -1, so you really don't know if the -1 means server disconnected or there is just no data in the buffer.

I cannot determine if read() is blocking or not, because the source trail ends in w5100.cpp getRXReceivedSize function, and I cannot find the implementation of readSnRX_RSR if it is blocking or not. I would still assume read() is blocking, otherwise, there is no point calling available() first before calling read().

So if the code below does not work, I'd have to say the problem is in the server.

Code:
    int length = 0;
    while (client.connected()) {
      debug("Still connected");
         while (client.available()) {
                 Serial.write(client.read());
                 length++;
         }
      debug("Done reading for now...");
   }
   client.stop();
   

to disable SD, set pin 4 to output and set it to high.
Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 140
Posts: 5873
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I cannot determine if read() is blocking or not, because the source trail ends in w5100.cpp getRXReceivedSize function, and I cannot find the implementation of readSnRX_RSR if it is blocking or not.

That function is not blocking with the condition that the "605 Bug" patch has been applied.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 14
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

... and you disabled the SD SPI interface on digital pin 4? Just checking. There have been more than a few posts here.

In the original sketch (i.e. before I started paring it down to debug), I was, and I was also writing to the SD card in order to cache the data. I've added the following code back in to setup():

Code:
pinMode(4, OUTPUT);
digitalWrite(4, HIGH);

The good news is that the Arduino made around 50 successful requests to Apache, and around 25 requests to the ruby server, each downloading the full payload. The bad news is that both runs still eventually hit a loop where the Arduino was still connected, but no data was available to be read. Subsequent runs saw the error reappear after as little as 10 requests, which is probably few enough to suggest that it's still not the root cause.

I'd be really interested in anyone who can run these examples on their own Arduinos to see if they definitely don't see this behaviour at all.

Additionally, would usage of the SD card while the ethernet is active cause interference? Everything I've read implies that they are intended to be used at the same time (e.g. serving files from the SD card, which is a classic example), so that seems unlikely...

"Still connected" and "Done reading for now" back-to-back means the server is not finished sending packets. It just did not receive a new packet during that check.

Yeah, I can see what you mean, but I am reasonably confident my reading of the wireshark logs - the Arduino is definitely due to send the server an ACK packet, but there's nothing making it onto the IP stack on the server machine. So in a sense, you are describing the situation; it's just that the server hasn't sent any new packets, because it's still waiting for an acknowledgement of the previous one.
Logged

SF Bay area
Offline Offline
Sr. Member
****
Karma: 2
Posts: 266
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok, I have determined read() to be a non blocking call, since available(), which is known to be non blocking calls getRXReceivedSize as well.
So calling read() essentially calls available() for you. So it is redundant to call available(). Really a non standard implementation.

Code:
int EthernetClient::available() {
  if (_sock != MAX_SOCK_NUM)
    return W5100.getRXReceivedSize(_sock);
  return 0;
}


you can use both ethernet and SD in the same sketch. You just need to disable both at setup(), and the library will take care of enabling/disabling.
Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 140
Posts: 5873
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok, I have determined read() to be a non blocking call, since available(), which is known to be non blocking calls getRXReceivedSize as well.
So calling read() essentially calls available() for you. So it is redundant to call available(). Really a non standard implementation.

That is correct. client.available() returns 0 if there are no characters in the rx buffer, and client.read() returns -1 (int value 65535) if there are no characters in the rx buffer. But neither are blocking.
Logged

SF Bay area
Offline Offline
Sr. Member
****
Karma: 2
Posts: 266
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok, one more try.

Code:
   int length = 0;
    while (client.connected()) {
      debug("Still connected");
         while (client.available()) {
                 byte buffer[64];
                 int count = 0;
                 while ((count=client.read(buffer,64))>0) {
                         Serial.write(buffer,count);
                 }
         }
      debug("Done reading for now...");
   }
   client.stop();

I am counting on the fact that if buffered read returns 0, we are guaranteed it is the eof based on this code in socket class. and that if buffered read returns zero, we are guaranteed available() and connected() will return false. Had it returned -1, then available() would be false but connected() would be true, and you will stay in the loop.

Code:
   if ( status == SnSR::LISTEN || status == SnSR::CLOSED || status == SnSR::CLOSE_WAIT )
    {
      // The remote end has closed its side of the connection, so this is the eof state
      ret = 0;
    }

minor edit.  actually, never mind this post, I just realized with available(), you are guaranteed at least 1 byte is available to read.
« Last Edit: March 07, 2012, 04:02:29 pm by doughboy » Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 140
Posts: 5873
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I like that code. That looks good to me.

Actually, that will be good when you start going the other way (like SD to ethernet). Sending one character at a time using client.write(byte) is a waste of internet resources. This works much better:
Code:
client.write(outBuffer,strlen(outBuffer));


Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 14
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I brought the Arduino home to see if the stalling behaviour occured on a different network, and the code from earlier (http://arduino.cc/forum/index.php/topic,95531.msg717698.html#msg717698) has already run ~350 requests without a single failure, and that's even without setting the SD pin to HIGH.

All fingers now point at the actual network at my office, which is both great to have isolated as the problem, and infuriating for obvious reasons.

Thanks again for all your help folks, I really appreciate it, and I definitely learned a lot!
Logged

Pages: 1 2 [3]   Go Up
Jump to: