Arduino Ethernet Shield. Sending a TCP Packet using only socket API

Hello, Arduino Community,

I have my Arduino Uno with an Ethernet Shield and I am trying to send a TCP packet containing 1 byte of TCP data over an established TCP connection using a socket API function send(). When this code is executed I get printed:

Initializing the w5100 chip and open a TCP socket...
Done opening socket
Connection established
Sending Data...

I would very appreciate if someone could show me where am I wrong. Please check out my code:

#include <Arduino.h>
#include <SPI.h>         // needed for Ethernet library communication with the W5100 (Arduino ver>0018)
#include <Ethernet.h>
#include <utility/w5100.h>
#include <utility/socket.h>
#include <util.h>

#include <avr/interrupt.h>

SOCKET s; // our socket 0 that will be opened in RAW mode

// set the src mac address
uint8_t smac[] = {  0x90, 0xA2, 0xDA, 0x0F, 0x46, 0x94 };
// set the dst mac address
uint8_t dmac[] = {  0x00, 0x21, 0xcc, 0x70, 0xf3, 0xae};

uint8_t src_ip[4] = {  192, 168, 0, 2};
uint8_t dst_ip[4] = {  192, 168, 0, 1};
uint8_t subnet_mask[4] = {  255, 255, 255, 0};
uint8_t gateway_ip[4] = {  192, 168, 0, 1};


uint8_t* src_mac = smac;
uint8_t* dst_mac = dmac;

uint8_t* dst_ip_addr = dst_ip;
uint8_t* src_ip_addr = src_ip;

uint16_t src_port = 3333;
uint16_t dst_port = 2222;

void setup()   {

  Serial.begin(115200);
  Serial.println("\r\nSetup...");
  Serial.print("\r\nInitializing the w5100 chip and open a TCP socket...");
  W5100.init();                        //
  W5100.writeSnMR(s, SnMR::TCP);     // set type of socket in Mode Register

  W5100.setMACAddress(smac);           // set own mac address
  W5100.setIPAddress(src_ip_addr);     // set own ip address
  W5100.writeSnPORT(s, src_port);      // set own port (for each socket different)
  W5100.setSubnetMask(subnet_mask);
  W5100.setGatewayIp(gateway_ip);


  W5100.writeSnDHAR(s, dst_mac);       // set destination mac address
  W5100.writeSnDIPR(s, dst_ip_addr);   // set destination ip
  W5100.writeSnDPORT(s, dst_port);     // set destination port

  W5100.execCmdSn(s, Sock_OPEN);
  Serial.print("\r\nDone opening socket");

  W5100.execCmdSn(s, Sock_CONNECT);

 if ( (W5100.readSnSR(s) & SnSR:: ESTABLISHED) != SnSR::ESTABLISHED) // check Status Register to find out if the connection was established
 Serial.print("\r\nConnection established");
 else
 Serial.print("\r\nCould not establish connection!!!");

 Serial.print("\r\nSending Data...");
 uint8_t data = 0x49;
 uint8_t* pdata = &data;

 if(!send(s,pdata,1))
 Serial.print("Could not send data");
 else
 Serial.print("Data sent");
}

void loop()
{
}

int main(void) {

  init();
  setup();

  while(true) {
    loop();
  }
}

As you can see it is never returned from the send() function, because the SEND_OK bit is not set in the Socket n Interrupt Register. In wireshark I also observe that the connection is established, but no data packet is sent.

The problem is solved.

I made a mistake: instead of continuously checking the connection status until it is established (in a while loop), I used an if statement.

Moreover, using "!=" in a while statement is correct, but it is not correctly used in my if statement. For this reason I didn't see that the connection at the moment of examining the if statement was actually not established.

Printing content of Interrupt, Status, TX Read Pointer and TX Write Pointer Registers to the serial port has helped me to debug the program and find where I was wrong. The correct code is:

Serial.print("\r\nExec a connect command");
W5100.execCmdSn(s, Sock_CONNECT);

while ( (W5100.readSnSR(s) & SnSR:: ESTABLISHED) != SnSR::ESTABLISHED){	// check Status Register to find out if the connection was established

}
Serial.print("\r\nConnection established");

Serial.print(", SnSR=0x");
Serial.print(W5100.readSnSR(s),HEX);

Serial.print(", SnIR=0x");
Serial.print(W5100.readSnIR(s),HEX);

Serial.print(", TX_WR=0x");
Serial.print(W5100.readSnTX_WR(s),HEX);

Serial.print(", TX_RD=0x");
Serial.print(W5100.readSnTX_RD(s),HEX);

I am interested in your code, and trying to test it on my system.

How do you test the connection? Meaning what program are you running on the other machine?

I am trying to do something similar and I have copied your code and pretty much got it working from my Arduino such that I can detect services on my home PC. My problem is I simply cannot get it to work with my iPhone. I get the TIMEOUT status back so it is as if there is no such service on the port number you indicated on the iPhone. Has this changed by any chance. I can do a simple ping and get it to work once my iPhone is not in sleep mode. My code is an exact copy of the code posted here except of course for the IP address and the MAC address. I have seen elsewhere that someone has done something similar from VB code on a PC. Struggling here so any suggestions would be helpful

NM