I am trying to use a TCP server and connect to it with a QTcpSocket client. Most of the time, the server and client happen to be on the same machine, but this is not a requirement. What I am trying to do is transfer a file from a running multithreaded process to a GUI that wants to share information used by both the server and the client.
The connect, etc seems to be just fine. In fact, the code appeared to work perfectly for a long time, but now that I am running it on different hardware, and on Ubuntu 12.04 instead of 10.04, I am occasionally getting embedded stray bytes in the received code--usually (but not always) nulls. I cant figure out whats wrong, and would welcome any advice.
Here is portion of the server that reads my file and sends the bytes to the connected client:
int fileSize;
printf(" about to open the file\n");
ini_fd = fopen (rov_ini_file_name, "r");
if(!ini_fd){
break;
}
fseek(ini_fd,0,SEEK_END);
fileSize = ftell(ini_fd);
fseek(ini_fd,0,SEEK_SET);
int totalBytesSent =0;
int line = 0;
int len;
while (!feof (ini_fd))
{
ch = fgets (&(my_line[0]), MAX_CHARACTER_COUNT - 1, ini_fd);
if (ch){
len = strlen(&(my_line[0]));
bytes_sent = sendto(tio.my_tio_port_table_entry.to_sock,
&(my_line[0]),
len,
0,
(struct sockaddr *) (&(tio.my_tio_port_table_entry.ToAddr)),
sizeof (tio.my_tio_port_table_entry.ToAddr));
totalBytesSent += bytes_sent;
line++;
//printf(" line %d bytes sent = %d total bytes = %d\n",line,bytes_sent,totalBytesSent);
}
}
len = sprintf(&(my_line[0]),"END_OF_INI_FILE");
bytes_sent = sendto(tio.my_tio_port_table_entry.to_sock,
&(my_line[0]),
len,
0,
(struct sockaddr *) (&(tio.my_tio_port_table_entry.ToAddr)),
sizeof (tio.my_tio_port_table_entry.ToAddr));
tio.my_tio_port_table_entry.connected = FALSE;
break;
Here is where I read the data being sent. This is the slot connected to the readyRead signal
void AlvGUI::readIniFromServer()
{
QByteArray inArray(iniClient->bytesAvailable(),0);
if(!iniStarted)
{
tempIniFile = new QTemporaryFile;
if(tempIniFile->open())
{
iniStarted = true;
}
else
{
// error should be here!
}
}
int bytesRead = iniClient->read(inArray.data(),inArray.size());
int endLoc = inArray.lastIndexOf("END_OF_INI_FILE");
if(-1 != endLoc)
{
inArray.chop(endLoc);
bytesRead = endLoc;
iniFinished = true;
}
tempIniFile->write(inArray.data(),bytesRead);
if(iniFinished)
{
tempIniFile->flush();
tempIniFile->close();
iniFile.close_ini();
char *theTempFile = strdup((char *)tempIniFile->fileName().toAscii().data());
iniFile.open_ini(theTempFile);
gotIni = true;
iniRequestTimer->stop();
makeGui();
free(theTempFile);
hotelSetup = true;
iniClient->abort();
}
}
as usual, asking a question makes me dig even deeper. I didn't have a tcp server problem--I confirmed that by using telnet to connect to my server and then redirected the output to a file--which was flawless
so I looked deeper into my code, and instead of truncating the incoming data, which was held in a QtByteArray, I was chopping it--which took the number of bytes read off of the end of the QtByteArray. Except that when I used the data() member function of the QtByteArray, I just got a char pointer back, and so got access to all of the data. The data was corrupted where I had done the chop()
Related
I am running ESP8266_RTOS_SDK_3.4 for an app that uses TCP to talk to a private port on a local server. In normal operation, it uploads large amounts of data to the server and receives acknowledgements that are usually less than 200 bytes: this always works fine. When I do an OTA update, where it's mainly receiving data, TCP recv fails on attempting to read the first block, and errno is set to 11 (EAGAIN). Even if I make the server send just 1024 bytes, the same thing happens.
This is the TCP connect and recv code:
bool net_tcp_connect (SENDER_DESTINATION * dest) {
struct sockaddr_in destAddr;
if (!find_host (dest->hostname)) {
return false;
}
memset(&destAddr, 0, sizeof(destAddr));
memcpy (&destAddr.sin_addr, findhost_ip (), sizeof (destAddr.sin_addr));
destAddr.sin_family = AF_INET;
destAddr.sin_port = htons (dest->port);
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
LOGEF("Create: errno %d", errno);
return false;
}
struct timeval tv;
tv.tv_sec = dest->timeout;
tv.tv_usec = 0;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));
if (connect(sock, (struct sockaddr *)&destAddr, sizeof(destAddr)) != 0) {
LOGEF("Connect: %s %d errno %d", findhost_str (), dest->port, errno);
EVENT_HERE ( );
net_tcp_close ();
return false;
}
return true;
}
// --------------------------------------------------------------------------------------------
int net_tcp_recv (void * buffer, int max_length) {
if (sock < 0)
return false;
int bytes_received = recv (sock, buffer, max_length, 0);
if (bytes_received < 0) {
LOGEF("Receive: errno= %d", errno);
net_tcp_close ();
bytes_received = 0;
}
return bytes_received;
}
EAGAIN can be a sign of a receive timeout, but the timeout is set to 30 seconds and the server usually sends out the first 32k bytes in less than a second.
The ESP8266 code does run OK on some access points and, as far as I can tell, the same code on an ESP32 runs OK on all access points.
Any suggestions for why this might happen, or things that I could try changing in the code or the ESP setup to make it work reliably on any access point?
I have a strange problem with trying to write data to a serial port.
I am running Ubuntu 16.04 on a NUC7i7DNBE, and am trying to make a serial connection to an Arduino UNO. The Serial API that I am using is found here: http://docs.ros.org/kinetic/api/serial/html/classserial_1_1Serial.html
I have written a simple program which opens the serial port "ttyACM0" to communicate with the arduino. I have tested this code on another computer running Ubuntu 16.04, and everything worked fine, the only permissions I had to set where adding the user to the dialout group.
On the NUC, however, I have added the user to the dialout group. This allowed the program to read from the Arduino, but it still does not write to the Arduino. The Arduino IDE will write to the Arduino just fine, but my program will not.
I am assuming that I am having trouble with serial write permissions in Ubuntu.
Steps I have taken:
I have added the user to the dialout group
I have added a rule in /etc/udev/rules.d/ which states:
SUBSYSTEMS=="tty", GROUP="dialout", MODE="0666"
Afterward, I sent the commands:
sudo chown root:root /etc/udev/rules.d/50-AVCusb.rules
sudo chmod 0644 /etc/udev/rules.d/50-AVCusb.rules
udevadm control --reload-rules
I followed some information found on stack exchange to get to this point:
https://unix.stackexchange.com/questions/111593/allow-non-root-user-to-read-write-dev-files
I have tried using an FTDI device to write to the Arduino port. The FTDI device uses the ttyUSB0 port rather than the ttyACM0 port. The result was the same; can read, but can't write.
I have also run my external hard-drive on the NUC to see if there was any kind of hardware issue. When I ran the program from my external hard drive, I had no problem reading from and writing to the Arduino.
I have not dealt much with Ubuntu permissions or ports in general, please help me find and upload any other information that you may need in order to help me solve this problem.
Code on NUC:
#include <ros/ros.h>
#include <serial/serial.h>
using namespace serial;
Serial ser;
static const uint8_t MOTOR_ID = 0;
void writeMotor(uint8_t byte)
{
size_t size = 4;
uint8_t buffer[size];
buffer[0] = 'G'; //PID
buffer[1] = 'O';
buffer[2] = MOTOR_ID; //address
buffer[3] = byte; //data byte
ser.write(buffer, size);
}
int main() {
ros::init(argc, argv, "servo_esc_driver");
std::string port = "/dev/ttyACM0";
Timeout timeout = Timeout(0, 0, 0, 0, 0);
bytesize_t bytesize = eightbits;
parity_t parity = parity_none;
stopbits_t stopbits = stopbits_one;
flowcontrol_t flowcontrol = flowcontrol_none;
try{
ser.setPort(port);
ser.setBaudrate(115200);
ser.setTimeout(timeout);
ser.setBytesize(bytesize);
ser.setParity(parity);
ser.setStopbits(stopbits);
ser.setFlowcontrol(flowcontrol);
ser.open();
}
catch (SerialException e) {
ROS_FATAL_NAMED("Failed to connect to the Arduino UNO, %s.", e.what());
ros::shutdown();
return 0;
}
uint8_t byte = 90;
writeMotor(byte);
}
Full Code on Arduino
#include <Servo.h>
const byte N = 2;
//Servo esc;
//Servo servo;
Servo servo[N];
//int escPos = 90;
//int servoPos = 90;
int pos[N];
static const byte ESC_PIN = 7;
static const byte SERVO_PIN = 8;
static const byte RPM_FEEDBACK_PIN = 0; //interrpt 0, pin 2
static const byte SERVO_FEEDBACK_PIN = A0;
//const float MUL = 0.7058823529; //180/255
unsigned long lastTime_servoFeedback = 0;
static const byte MOTOR_ID = 0; //ID for differentiating data received and sent over serial connections
static const byte SERVO_ID = 1;
//added for motor data timeout safety feature
static const unsigned long MOTOR_DATA_TIMEOUT = 200; //4 x 50 ms (50 ms time period expected)
static unsigned long lastTimeMotorData = 0;
static const byte NEUTRAL = 90;
unsigned long last_rpm_pulse_update_ms = 0; //used for detecting a stopped car, and rejecting old data when writing to the serial port
unsigned long last_rpm_pulse_time_us = 0;//keeps track of rpms by comparing to system timer
static const long REV_PERIOD_MAX_US = 100000; //in us
unsigned long rev_period = REV_PERIOD_MAX_US; //100 ms is considered too long to be in motion
boolean forward = true;
/*Scratch that, I want these parameters set in ROS:
static const float wheel_radius = 0.05 // meters
static const float revs_to_mps_MUL = //assuming 2.85 gear ratio for brushless motor differential: https://forums.traxxas.com/showthread.php?9080733-Diff-gear-ratios
*/
//boolean rpm_period_updated = false; //rpms must be updated every 100 ms, otherwise the car has stopped, and velocity data should show 0 m/s
void rpm_feedback()
{
//Serial.println("in rpm_feedback");
last_rpm_pulse_update_ms = millis(); //notice the 'ms' here we want to use millisecond for checking whether or not data is valid. millis() can count up to 50 days while micros() only counts up to 70 minutes, thus millis() is used here.
unsigned long time_now = micros(); //use time now for accurate time calculations
unsigned long rev_period_temp = time_now - last_rpm_pulse_time_us; //get spur-gear revolution period
if(rev_period_temp > 0) rev_period = rev_period_temp; //revs are within
else rev_period = REV_PERIOD_MAX_US;
last_rpm_pulse_time_us = time_now; //using 'time_now' ensures that the time taken to get to this point in code does not interfere with rev_period accuracy - - - micros(); //reset time
if(pos[MOTOR_ID] < 90) //determine the direction that the vehicle is traveling in
{
forward = false;
}else forward = true;
//rpm_period_updated = true; not needed, only last_rpm_pulse_time_ms is needed for checking
}
void setup() {
// put your setup code here, to run once:
pinMode(RPM_FEEDBACK_PIN, INPUT_PULLUP);
attachInterrupt(RPM_FEEDBACK_PIN, rpm_feedback,FALLING); //arduino reference recommends using digitalPinToInterrupt(RPM_FEEDBACK_PIN) but the command is not recognized here
analogReference(EXTERNAL); //Using external reference for servo position
for(int i = 0; i < N; i++) //initialize
{
pos[i] = 90;
servo[i].attach(ESC_PIN + i);
}
Serial.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
if(Serial.available() >= 1)
{
if(Serial.read() == 'G')
{
unsigned long t = millis();
while((Serial.available() < 3) && ((millis() - t) < 10)); //wait for the rest of the package, or timeout
if(Serial.available() >= 3)
{
char buf[3];
Serial.readBytes(buf, 3);
if((buf[0] == 'O') && (buf[1] >= 0) && (buf[1] < 2))
{
pos[buf[1]] = byte(buf[2]);
if(buf[1] == MOTOR_ID) lastTimeMotorData = millis(); //time stamp of last motor data retrieval
//Serial.print("buf[2]: ");
//Serial.println(byte(buf[2]), DEC);
//Serial.print("pos: ");
//Serial.println(pos[buf[1]]);
}
}
}
}
if((millis() - lastTimeMotorData) > MOTOR_DATA_TIMEOUT) pos[MOTOR_ID] = NEUTRAL; //stop the motor if data is not being received
for(int i = 0; i < N; i++)
{
servo[i].write(pos[i]);
}
if((millis() - lastTime_servoFeedback) >= 50) // 20Hz 20) //50Hz matches current ROS driver settings
{
lastTime_servoFeedback = millis();
int servo_feedback = analogRead(SERVO_FEEDBACK_PIN);
Serial.write('G'); //PID
Serial.write('O');
Serial.write(SERVO_ID);
//Serial.print(servo_feedback);
Serial.write(lowByte(servo_feedback));
Serial.write(highByte(servo_feedback));
//Serial.println(servo_feedback);
float rev_frequency;
if((last_rpm_pulse_update_ms + 100) < millis()) rev_frequency = 0; //use millis() since it can count up to 50 days, and will not have a chance of a hiccup after 70 minutes of using micros()
//instead, correct period when slowing down, also stop when the maximum threshold is reached
//if((micros() - last_rpm_pulse_time_us) >= REV_PERIOD_MAX_US) rev_frequency = 0; //car is stopped in this case. I decided not to try correcting the period as mentioned above
else rev_frequency = (float) 1/rev_period*1000000;
byte *rev_freq_bytes_to_transmit = (byte *) &rev_frequency;
if(forward == false) rev_frequency = -rev_frequency; //a negative frequency is used for reverse
Serial.write('G'); //PID
Serial.write('O');
Serial.write(MOTOR_ID); //used for addressing
Serial.write(rev_freq_bytes_to_transmit, 4);
}
}
Some good information may be:
snuc#usuavc:~$ udevadm info -a -n /dev/ttyACM0
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device '/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.0/tty/ttyACM0':
KERNEL=="ttyACM0"
SUBSYSTEM=="tty"
DRIVER==""
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.0':
KERNELS=="1-4:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="cdc_acm"
ATTRS{authorized}=="1"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceClass}=="02"
ATTRS{bInterfaceNumber}=="00"
ATTRS{bInterfaceProtocol}=="01"
ATTRS{bInterfaceSubClass}=="02"
ATTRS{bNumEndpoints}=="01"
ATTRS{bmCapabilities}=="6"
ATTRS{supports_autosuspend}=="1"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-4':
KERNELS=="1-4"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="02"
ATTRS{bDeviceProtocol}=="00"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="8"
ATTRS{bMaxPower}=="100mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 2"
ATTRS{bcdDevice}=="0001"
ATTRS{bmAttributes}=="c0"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="4"
ATTRS{devpath}=="4"
ATTRS{idProduct}=="0043"
ATTRS{idVendor}=="2341"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Arduino (www.arduino.cc)"
ATTRS{maxchild}=="0"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="removable"
ATTRS{serial}=="55330313635351207081"
ATTRS{speed}=="12"
ATTRS{urbnum}=="6990"
ATTRS{version}==" 1.10"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1':
KERNELS=="usb1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{authorized_default}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="09"
ATTRS{bDeviceProtocol}=="01"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{bMaxPower}=="0mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0415"
ATTRS{bmAttributes}=="e0"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="1"
ATTRS{devpath}=="0"
ATTRS{idProduct}=="0002"
ATTRS{idVendor}=="1d6b"
ATTRS{interface_authorized_default}=="1"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Linux 4.15.0-32-generic xhci-hcd"
ATTRS{maxchild}=="12"
ATTRS{product}=="xHCI Host Controller"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="unknown"
ATTRS{serial}=="0000:00:14.0"
ATTRS{speed}=="480"
ATTRS{urbnum}=="76"
ATTRS{version}==" 2.00"
looking at parent device '/devices/pci0000:00/0000:00:14.0':
KERNELS=="0000:00:14.0"
SUBSYSTEMS=="pci"
DRIVERS=="xhci_hcd"
ATTRS{broken_parity_status}=="0"
ATTRS{class}=="0x0c0330"
ATTRS{consistent_dma_mask_bits}=="64"
ATTRS{d3cold_allowed}=="1"
ATTRS{dbc}=="disabled"
ATTRS{device}=="0x9d2f"
ATTRS{dma_mask_bits}=="64"
ATTRS{driver_override}=="(null)"
ATTRS{enable}=="1"
ATTRS{irq}=="122"
ATTRS{local_cpulist}=="0-7"
ATTRS{local_cpus}=="ff"
ATTRS{msi_bus}=="1"
ATTRS{numa_node}=="-1"
ATTRS{revision}=="0x21"
ATTRS{subsystem_device}=="0x2070"
ATTRS{subsystem_vendor}=="0x8086"
ATTRS{vendor}=="0x8086"
looking at parent device '/devices/pci0000:00':
KERNELS=="pci0000:00"
SUBSYSTEMS==""
DRIVERS==""
I decided that the problem was with the ROS version of serial. I decided to try some native linux library, termios, and had success writing to the port!
I found this example code:
https://en.wikibooks.org/wiki/Serial_Programming/Serial_Linux
The problem lies in the ros serial installation somehow.
Don't know if you still want to solve this with serial/serial.h, but I think that your problem might be in the timeout settings.
I'm telling you this, 'cause I had the exact same problem, I could read the incoming data, but couldn't write.
The /dev/ttyUSB0 permission was ok, but not the timeout.
I found the following config on internet, gave a try and work. Now I can read and write.
try{
ser.setPort("/dev/ttyUSB0");
ser.setBaudrate(9600);
serial::Timeout to = serial::Timeout::simpleTimeout(10);
ser.setTimeout(to);
ser.open();
return true;
}
catch (SerialException e) {
return 0;
I'm very new to the Microchip line and I'm currently using the Pic32 Ethernet Starter Kit 2. I've been playing and testing all aspects of this product and I'm currently working with the Generic TCPIP Servo demo from Harmony. I can load the app on the Chip and log into it with Telnet. I can also see it working if I type in say "h" it will echo back "hH" as it should. Because in this demo it runs a ToUpper line on it. What I'm looking to try is to type "hello" in telnet then have it send back "World" Just something simple to get me rolling with this. Below is the current section of code that reads the incoming data converts it to Upper and sends back out.
case APP_TCPIP_SERVING_CONNECTION:
{
if (!TCPIP_TCP_IsConnected(appData.socket))
{
appData.state = APP_TCPIP_CLOSING_CONNECTION;
SYS_CONSOLE_MESSAGE("Connection was closed\r\n");
break;
}
int16_t wMaxGet, wMaxPut, wCurrentChunk;
uint16_t w, w2;
uint8_t AppBuffer[32];
//uint8_t AppBuffer2[] = "This is a Test";
// Figure out how many bytes have been received and how many we can transmit.
wMaxGet = TCPIP_TCP_GetIsReady(appData.socket); // Get TCP RX FIFO byte count
wMaxPut = TCPIP_TCP_PutIsReady(appData.socket); // Get TCP TX FIFO free space
// Make sure we don't take more bytes out of the RX FIFO than we can put into the TX FIFO
if(wMaxPut < wMaxGet)
wMaxGet = wMaxPut;
// Process all bytes that we can
// This is implemented as a loop, processing up to sizeof(AppBuffer) bytes at a time.
// This limits memory usage while maximizing performance. Single byte Gets and Puts are a lot slower than multibyte GetArrays and PutArrays.
wCurrentChunk = sizeof(AppBuffer);
for(w = 0; w < wMaxGet; w += sizeof(AppBuffer))
{
// Make sure the last chunk, which will likely be smaller than sizeof(AppBuffer), is treated correctly.
if(w + sizeof(AppBuffer) > wMaxGet)
wCurrentChunk = wMaxGet - w;
// Transfer the data out of the TCP RX FIFO and into our local processing buffer.
TCPIP_TCP_ArrayGet(appData.socket, AppBuffer, wCurrentChunk);
// Perform the "ToUpper" operation on each data byte
for(w2 = 0; w2 < wCurrentChunk; w2++)
{
i = AppBuffer[w2];
if(i >= 'a' && i <= 'z')
{
i -= ('a' - 'A');
AppBuffer[w2] = i;
}
else if(i == '\e') //escape
{
appData.state = APP_TCPIP_CLOSING_CONNECTION;
SYS_CONSOLE_MESSAGE("Connection was closed\r\n");
}
}
// Transfer the data out of our local processing buffer and into the TCP TX FIFO.
SYS_CONSOLE_PRINT("Server Sending %s\r\n", AppBuffer);
TCPIP_TCP_ArrayPut(appData.socket, AppBuffer, wCurrentChunk);
// No need to perform any flush. TCP data in TX FIFO will automatically transmit itself after it accumulates for a while. If you want to decrease latency (at the expense of wasting network bandwidth on TCP overhead), perform and explicit flush via the TCPFlush() API.
}
}
break;
Thanks in advance.
PBSnake
case APP_TCPIP_SERVING_CONNECTION:
{
static uint8_t message[] = "Hello";
static uint16_t pos = 0;
if (!TCPIP_TCP_IsConnected(appData.socket))
{
pos = 0;
appData.state = APP_TCPIP_CLOSING_CONNECTION;
SYS_CONSOLE_MESSAGE("Connection was closed\r\n");
break;
}
int16_t wMaxGet, wMaxPut, wCurrentChunk;
uint16_t w, w2;
uint8_t AppBuffer[32];
//uint8_t AppBuffer2[] = "This is a Test";
// Figure out how many bytes have been received and how many we can transmit.
wMaxGet = TCPIP_TCP_GetIsReady(appData.socket); // Get TCP RX FIFO byte count
wMaxPut = TCPIP_TCP_PutIsReady(appData.socket); // Get TCP TX FIFO free space
// Make sure we don't take more bytes out of the RX FIFO than we can put into the TX FIFO
if(wMaxPut < wMaxGet)
wMaxGet = wMaxPut;
// Process all bytes that we can
// This is implemented as a loop, processing up to sizeof(AppBuffer) bytes at a time.
// This limits memory usage while maximizing performance. Single byte Gets and Puts are a lot slower than multibyte GetArrays and PutArrays.
wCurrentChunk = sizeof(AppBuffer);
for(w2 = 0; w2 < wCurrentChunk; w2++)
{
i = AppBuffer[w2];
if (i == message[pos])
{
pos++;
if (pos == strlen(message))
{
pos = 0;
strcpy(AppBuffer, "World");
SYS_CONSOLE_PRINT("Server Sending %s\r\n", AppBuffer);
TCPPutArray(MySocket, AppBuffer, strlen(AppBuffer));
}
}
else
{
pos = 0;
}
if(i == '\e') //escape
{
TCPServerState = SM_CLOSING;
}
}
}
break;
I want to set up TCP server on windows and TCP client on ESP32. Main idea is to send String to ESP32 change it and send it back to server, but I'm really new with all of this stuff and got stuck on setting up TCP client on ESP32. Examples or references would be really helpful.
int create_ipv4_socket()
{
struct addrinfo hints;
struct addrinfo *res;
struct in_addr *addr;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
int err = getaddrinfo(UDP_IPV4_ADDR, TCP_PORT, &hints, &res);
if(err != 0 || res == NULL) {
printf("DNS lookup failed err=%d res=%p\n", err, res);
return -1;
}
/* Code to print the resolved IP.
Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */
addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
printf("DNS lookup succeeded. IP=%s\n", inet_ntoa(*addr));
l_sock = socket(res->ai_family, res->ai_socktype, 0);
if(l_sock < 0) {
printf("... Failed to allocate socket.\n");
freeaddrinfo(res);
return -1;
}
struct timeval to;
to.tv_sec = 2;
to.tv_usec = 0;
setsockopt(l_sock,SOL_SOCKET,SO_SNDTIMEO,&to,sizeof(to));
if(connect(l_sock, res->ai_addr, res->ai_addrlen) != 0) {
printf("... socket connect failed errno=%d\n", errno);
close(l_sock);
freeaddrinfo(res);
return -1;
}
printf("... connected\n");
freeaddrinfo(res);
// All set, socket is configured for sending and receiving
return l_sock;
}
From this forum https://www.esp32.com/viewtopic.php?t=5965
How do you communicate with your ESP? if you communicate through UART, just send him AT command he need by writing on the UART port:
"AT+CIPSTATUS\r\n"
and then wait for his response.
If you are connected to your ESP32 directly with your computer, just use putty and directly send AT command to it.
A non exhaustive list of AT's command can be found here:
https://www.espressif.com/sites/default/files/documentation/esp32_at_instruction_set_and_examples_en.pdf
I used OpenCV on VS10 to stream video from my webcam. I also used winsock2 to transmit a message and an image in the same computer from server-client TCP/IP (local host). Now I'm trying to stream video in real-timing. I don't know if with function "send" I can specify the length of each frame because I think that it can also send a constant char. Anyone know what function could I use to solve my problem?
Source code:
Server.cpp
#include "Server.h"
using namespace std;
//Our main function
//void main()
int _tmain(int argc, _TCHAR* argv[])
{
//We have to start de Winsock-dll
long answer;
WSAData wsaData;
WORD DLLVERSION;
DLLVERSION = MAKEWORD (2,1);
//Stard the dll
answer = WSAStartup(DLLVERSION, &wsaData);
//The dll was started, now I use the winsock funcitions in the program
//Structure for the sockets
SOCKADDR_IN addr;
//addr = our structure
int addrlen = sizeof(addr);
//Now we have to create our sockets
//sListen = socket which is listening for incoming connection
SOCKET sListen;
//sConnect = socket which is operating if a connection was found!
SOCKET sConnect;
//Now we have to setup our sockets:
//AF_INET = means that our socket belongs to the internet family
//SOCK_STREAM = means that our socket is a connection-orientated socket
sConnect = socket(AF_INET, SOCK_STREAM, NULL);
//Now we have to setup our structure
//inet_addr = IP of our socket (I use 127.0.0.1...this is the loopback adress)
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//Retype the family
addr.sin_family = AF_INET;
//Now we have to setup the port in the structure;
//Now our server has the IP: 127.0.0.1 and the port 1234
addr.sin_port = htons (1234);
//Now we have to setup our sListen socket
sListen = socket(AF_INET, SOCK_STREAM, NULL);
//Now we blind the socket
//The socket becomes the structure addr
bind(sListen, (SOCKADDR*)&addr, sizeof(addr));
//We have to say that the socket is listening for an incoming connection
listen(sListen, SOMAXCONN);
//SOMAXCON means that the server is listenning without any limit
//We have to start the capture of the frames to send it
//Well first of all initialize the frames and the default camera
//Using OpenCV
CvCapture *capture = 0;
IplImage *frame = 0;
int key = 0;
capture = cvCaptureFromCAM(0);
//At last we have to say what the serve sould do if a connection was found!
//For this we create a endless loop:
for(;;)
{
cout << "Waiting for an incoming connection" <<endl;
//if a connection was found << "..." <<endl
if(sConnect = accept(sListen, (SOCKADDR*)&addr, &addrlen))
{
cout << "A connection was found" <<endl;
//Second part in reference to Youtube 2
//1r: The server should send a message with the funcion send();
//The number of the letters +1
//Ex: Number of the letters: 14+1=15
answer = send(sConnect, "Bonjour",8, NULL);
//*************************Third part of the project
//Sending an image captured from the cam
//always check
if ( !capture )
{
fprintf( stderr, "Cannot open initialize webcam!\n" );
return 1;
}
//create a window for the video
cvNamedWindow( "server", CV_WINDOW_AUTOSIZE );
while( key != 'q' )
{
//get a frame
frame = cvQueryFrame(capture);
//always check
if( !frame ) break;
//display current frame
cvShowImage( "server", frame );
//exit if user press 'q'
key = cvWaitKey(1);
}
char StartStream(IplImage *frame);
int streamSize(IplImage *frame);
if(frame!=0)
{
return sizeof(*frame->imageData);
}
char* buffer = new char[10000];
int len = 10000;
//int sent = 0;
for(int i=0; i<len; i+= answer)
{
answer = send(sConnect, buffer+i, len-i, 0);
}
}
//free memory
cvDestroyWindow( "server" );
cvReleaseCapture( &capture );
}
return 0;
}
Client.cpp
#include "Client.h"
using namespace std;
//void main()
int _tmain(int argc, _TCHAR* argv[])
{
string confirm;
char message[200];
string strmessage;
//IplImage *pImg;
//Start the functions of the Winsock-DLL
long answer;
WSAData wsaData;
WORD DLLVersion;
DLLVersion = MAKEWORD(2,1);
answer = WSAStartup(DLLVersion, &wsaData);
//Setup our Sockets and SOCKADDR_IN
SOCKADDR_IN addr;
//we will need addrlen later maybe!
int addrlen = sizeof(addr);
//Now setup our Socket
SOCKET sConnect;
sConnect = socket(AF_INET, SOCK_STREAM, NULL);
//IP of our server
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//Now we have to retype de family
addr.sin_family = AF_INET;
//Port of our server
addr.sin_port = htons(1234);
//Now we will ask the client if he wants to connect
cout << "Do you want to connect to your server? [Y/N]" <<endl;
cin >> confirm;
//If the user don't want to connect the client will close
if (confirm == "N")
{
exit(1);
}
else
{
if (confirm == "Y")
{
//function connect
connect(sConnect, (SOCKADDR*)&addr, sizeof(addr));
//Our client is working
//Now we program the client that he should recv a message from the server
//Our client should receive the message with the function recv();
//With new char "message"
answer = recv(sConnect, message, sizeof(message), NULL);
//The client should display the message
//With new string strmessage
strmessage = message;
cout << strmessage <<endl;
//the client also should display the image recived
char* buffer = new char[10000];
int len = 10000;
//int rec = 0;
int i=0;
for(int i=0; i<len; i+= answer)
{
while (answer = recv(sConnect, buffer+i, len-i, 0))
{
IplImage *frame = cvCreateImage(cvSize(640,480), 8, 3);
frame->imageData = (char *)buffer;
cvNamedWindow( "client", CV_WINDOW_AUTOSIZE );
cvShowImage( "client", frame );
}
return 0;
}
getchar();
}
}
getchar();
}
I receive the message and the confirmation of the connection in the server. And also it opens the webcam but the client doesn't receive anything.
You can try the cv_video_server and client.