I am trying to do some experiments with Arduino, Ethernet Shield and Xbee Shield.
I demonstrate my set up board like this:
Group 1: Arduino Uno + Xbee shield : broadcast the signal
Group 2: Arduino Uno + Xbee shield + Ethernet shield: receive the signal from
group 1, get the signal strength from AT command and print it into the browser.
The problem here is I can't get the result after sending to the Serial my ATDB command, actually, I am not sure it did worked as I expected.
Here is the code that I used to retrieve the signal strength.
int data;
void setup()
{
Serial.begin(9600);
}
void receiver_checker(){
delay(1200);
Serial.print("+++");
delay(1200);
bool bOK = false;
while (Serial.available() > 0) {
Serial.write(Serial.read());
bOK = true;
}
if(bOK)
{
Serial.println();
Serial.println("ATDB");
delay(100);
while (Serial.available() > 0) {
Serial.write(Serial.read());
}
Serial.println();
}
Serial.println();
}
void loop()
{
while(Serial.available() > 0){
data = Serial.read();
if(data == '1'){
// Broadcaster 1
//Serial.println("1------------------");
receiver_checker();
}
}
}
This part worked as I expected, it printed out in hex number the signal strength of the last package that it received.
Here is the code I combined the previous one and the server part from Web Server tutorial:
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xCA, 0xFE, 0x00, 0x00, 0x00, 0x02
};
IPAddress ip(1, 1, 1, 2);
int data;
int count = 0;
char result;
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
server.begin();
// Serial.print("server is at ");
// Serial.println(Ethernet.localIP());
}
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();
// Serial.write(c);
// 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>");
if (Serial.available() > 0) {
// read the oldest byte in the serial buffer:
data = Serial.read();
// if it's a capital H (ASCII 72), turn on the LED:
if (data == '1') {
count += 1;
client.print("The number of times:");
client.print(count);
result = receiver_checker();
client.print("========================");
client.print(result);
client.print("========================");
}
}
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");
}
}
char receiver_checker(){
char signal;
delay(1200);
Serial.print("+++");
delay(1200);
bool bOK = false;
while (Serial.available() > 0) {
Serial.write(Serial.read());
bOK = true;
}
if(bOK)
{
Serial.println();
Serial.println("ATDB");
delay(100);
while (Serial.available() > 0) {
signal = Serial.read();
}
Serial.println();
}
Serial.println();
return signal;
}
If there is another way to interact with the Xbee shield not go through Serial like I ask and get response directly, please let me know!
Your receiver_checker() function is reading characters back from the XBee module, and just returning the last character received, which is likely a carriage return or line feed.
Update the function to return an int, and replace your while (Serial.available() > 0) with the following:
signal = (int) strtoul(Serial.readString().c_str(), 0, 16);
That's for when the XBee returns a hexadecimal value. If it's returning a decimal value, change the 16 parameter to a 10.
Related
I am making a web server with an ESP32D, I am programming it from the Arduino IDE and I have a function with spaghetti code which I want to refactor with switch case,
this is my function, which i am calling in the void loop()
void control(){
if (header.indexOf("GET /2/on") >= 0) {
Serial.println("GPIO 2 on");
output2State = "on";
digitalWrite(output2, HIGH);
} else if (header.indexOf("GET /2/off") >= 0) {
Serial.println("GPIO 2 off");
output2State = "off";
digitalWrite(output2, LOW);
} else if (header.indexOf("GET /15/on") >= 0) {
Serial.println("GPIO 15 on");
output15State = "on";
digitalWrite(output15, HIGH);
} else if (header.indexOf("GET /15/off") >= 0) {
Serial.println("GPIO 15 off");
output15State = "off";
digitalWrite(output15, LOW);
}
}
void function_loop(){
WiFiClient client = server.available(); // Listen for incoming client
// Serial.println(typeOf(client));
if (client) { // If a new client connects,
currentTime = millis();
previousTime = currentTime;
Serial.println("New Client."); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
currentTime = millis();
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
control();
}
How could I do to be able to pass it to switch case? I have no idea how to pass the variable to modify (in this case the header.indexOf)
It isn't clear from your example what type your header is, but I'm guessing it is a String.
Send header to control() like this
control(header);
and declare control() like this
void control(String& header) {
I have a UDP Server which sends data continuously. I want to receive all the packets sent by the server.
On server side I have two threads. One thread continuously reads data from the file and puts into deque. Another thread reads data from the deque and sends to the UDP client continuously. The client code continuously receives data from the server.
I have variables to keep the count of the number of bytes sent in server code and the number of bytes received in client code.
There is huge difference between the two. The server sends about 93 MB but the client receives only 3 - 5 MB.
How can I receive all the data sent by the Server?
Please find the server and client code below.
Server Code:
#define MAX_BUFFER_SIZE 1400
typedef struct
{
T_UCHAR buffer[MAX_BUFFER_SIZE];
DWORD buf_size;
}RAWDATA_LOG;
deque<RAWDATA_LOG> m_RawdataLog;
void TransmitContinuous()
{
if (m_sock_type_tcp == SOCK_UDP)
{
fileReadComplete=false;
//start data transmission thread
pWin_thread=AfxBeginThread(StartDataTransmitThread, (LPVOID) this);
ReadFromFile();
}
}
void ReadFromFile()
{
int bytesRead=0;
m_no_of_bytes = MAX_BUFFER_SIZE;
BYTE input_buf[MAX_BUFFER_SIZE]={'\0'};
GetDlgItemText(IDEBC_FILENAME,m_fileInput);
m_InputFile=NULL;
/*opening the file to read*/
m_InputFile = _tfopen(m_fileInput,L"rb");
if(m_InputFile == NULL)
{
AfxMessageBox(L"Unable to open the Input file");
}
else
{
while(!feof(m_InputFile))
{
bytesRead=fread(input_buf,1,m_no_of_bytes,m_InputFile);
writeRawdataToDeque(input_buf,m_no_of_bytes);
noofBytesReadfromFile+=bytesRead;
}
fileReadComplete=true;
}
}
void writeRawdataToDeque(T_UCHAR *buffer,T_S32 size)
{
T_S32 temp_size = size;
T_S32 size_counter = 0;
RAWDATA_LOG temp_rawDataStruct;
while(temp_size>0)
{
if(temp_size <= MAX_BUFFER_SIZE)
{
memcpy(temp_rawDataStruct.buffer,&buffer[size_counter],temp_size);
temp_rawDataStruct.buf_size = temp_size;
noofBytesWrittentoDeque+=temp_size;
}
else
{
memcpy(temp_rawDataStruct.buffer,&buffer[size_counter],sizeof(temp_rawDataStruct.buffer));
temp_rawDataStruct.buf_size = MAX_BUFFER_SIZE;
noofBytesWrittentoDeque+=MAX_BUFFER_SIZE;
}
CSingleLock datalock(&m_Cs_RawDataLog);
datalock.Lock();
m_RawdataLog.push_back(temp_rawDataStruct);
datalock.Unlock();
memset(&temp_rawDataStruct,0,sizeof(temp_rawDataStruct));
size_counter += MAX_BUFFER_SIZE;
temp_size = temp_size - MAX_BUFFER_SIZE;
}
}
unsigned int StartDataTransmitThread (LPVOID param)
{
RAWDATA_LOG temp_rawDataBuf;
int byesWritten=0;
CString tmpStr;
while(1)
{
if(!m_RawdataLog.empty())
{
CSingleLock datalock(&m_Cs_RawDataLog);
datalock.Lock();
temp_rawDataBuf = m_RawdataLog.front();
m_RawdataLog.pop_front();
datalock.Unlock();
//transmit the data through socket
byesWritten=WritetoClient(clientIp,clientPort,(const LPBYTE)&temp_rawDataBuf, MAX_BUFFER_SIZE);
noofBytesTransmitted+=byesWritten;
}
else
{
if(fileReadComplete == true)
{
break;
}
}
}
return true;
}
bool CreateServer(char ipaddr[],int port)
{
sockaddr_in ServerSockAddr;
WORD m_wVersionRequested;
WSADATA m_wsaData;
int m_wsaErr;
ServerSockAddr.sin_addr.s_addr=inet_addr("192.168.11.80");
ServerSockAddr.sin_family = AF_INET;
ServerSockAddr.sin_port = htons(2011);
m_wVersionRequested = MAKEWORD(2, 2);
m_wsaErr = WSAStartup(m_wVersionRequested, &m_wsaData);
if (m_wsaErr != 0)
{
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
MessageBox(L"WSAStartup failed with error:" + m_wsaErr);
return 1;
}
SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (INVALID_SOCKET != sock)
{
if ( SOCKET_ERROR == bind(sock,(struct sockaddr *) & ServerSockAddr, sizeof(ServerSockAddr)))
{
int b= GetLastError();
closesocket( sock );
return false;
}
}
else
{
closesocket( sock );
return false;
}
m_hComm = (HANDLE) sock;
}
int WritetoClient(char ipaddr[],int port,BYTE buf[],int len)
{
sockaddr_in clientSockAddr;
int res=0;
SOCKET s = (SOCKET) m_hComm;
clientSockAddr.sin_addr.s_addr=inet_addr("192.168.11.80");
clientSockAddr.sin_family = AF_INET;
clientSockAddr.sin_port = htons(port);
res = sendto( s, (const char *)buf, len, 0, (SOCKADDR *) &clientSockAddr, sizeof(clientSockAddr));
return res;
}
Client Code:
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32")
#define BUFSIZE 1000000
int _tmain(int argc, _TCHAR* argv[])
{
SOCKET sockfd;
int portno, n;
int serverlen;
struct sockaddr_in serveraddr;
struct hostent *server;
char *hostname;
char buf[BUFSIZE];
int BytesReceived=0;
int buff_size=1000000;
WORD m_wVersionRequested;
WSADATA m_wsaData;
int m_wsaErr;
m_wVersionRequested = MAKEWORD(2, 2);
m_wsaErr = WSAStartup(m_wVersionRequested, &m_wsaData);
if (m_wsaErr != 0)
{
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
printf("WSAStartup failed with error:");
return 1;
}
/* socket: create the socket */
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sockfd < 0)
{
printf("ERROR opening socket");
}
else
{
/* build the server's Internet address */
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(2010);
serveraddr.sin_addr.s_addr=inet_addr("192.168.11.80");
/* send the message to the server */
serverlen = sizeof(serveraddr);
setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,(char *)(&buff_size), sizeof(buff_size));
if ( SOCKET_ERROR == bind(sockfd,(struct sockaddr *) & serveraddr, sizeof(serveraddr)))
{
printf("Bind Error");
int a = GetLastError();
printf("Error ID:%d",a);
}
else
{
printf("Reading From Server:\n");
while(1)
{
n = recvfrom(sockfd, buf, sizeof(buf), 0,(struct sockaddr *) &serveraddr, &serverlen);
if (n < 0)
{
printf("ERROR in recvfrom\n");
int b = GetLastError();
printf("Error ID:%d\n",b);
}
else
{
BytesReceived+=n;
TRACE("\nTotal Bytes Received:%d\n",BytesReceived);
}
}
}
}
getchar();
return 0;
}
I see a couple of issues with your code.
On the server side, you are binding the server's socket to 192.168.11.80 AND you are sending packets to 192.168.11.80 as well, instead of sending them to whichever IP address is specified in the ipaddr parameter of the WritetoClient() function.
On the client side, you are bind()'ing the client's socket to the server's IP address.
This setup will only work if the client and server are running on the same machine. It will not work between multiple machines connected through a network.
You need to bind the client to an IP address that is local to the client's own machine, not to the server's IP address. And your server needs to send packets to the IP address that the client is actually bound to.
If you want to ensure that your client receives data only from the server's IP address, and not from other machines that may happen to be sending data over the same network, you can optionally connect() the client's socket to the server's IP address (yes, you can use connect() with UDP).
bind() is for establishing a socket's local IP address. connect() is for establishing a socket's remote/peer IP address.
Since you are (potentially) not binding the client's socket correctly, and/or (potentially) not sending to the correct IP, you are likely receiving data that you are not expecting from somewhere else. That could explain the large discrepancy you are seeing. I would suggest having your client output the data it actually receives, so you can make sure it is receiving what you are expecting, eg:
n = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *) &serveraddr, &serverlen);
if (n == SOCKET_ERROR)
{
int b = WSAGetLastError();
printf("ERROR in recvfrom\nError ID:%d\n",b);
}
else
{
BytesReceived += n;
TRACE("\nMessage Received from %s:%hu: '%.*s'", inet_ntoa(serveraddr.sin_addr), ntohs(serveraddr.sin_port), n, buf);
TRACE("\nTotal Bytes Received: %d\n", BytesReceived);
}
I'm reading "Unix Networking Programming" the 3ed edition.
I encounter a question in 6.8 section "TCP Echo Server (Revisited)", here present code as below:
#include "unp.h"
int
main(int argc, char **argv)
{
int i, maxi, maxfd, listenfd, connfd, sockfd;
int nready, client[FD_SETSIZE];
ssize_t n;
fd_set rset, allset;
char buf[MAXLINE];
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
maxfd = listenfd; /* initialize */
maxi = -1; /* index into client[] array */
for (i = 0; i < FD_SETSIZE; i++)
client[i] = -1; /* -1 indicates available entry */
FD_ZERO(&allset);
FD_SET(listenfd, &allset);
for ( ; ; ) {
rset = allset; /* structure assignment */
nready = Select(maxfd+1, &rset, NULL, NULL, NULL);
if (FD_ISSET(listenfd, &rset)) { /* new client connection */
clilen = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
for (i = 0; i < FD_SETSIZE; i++)
if (client[i] < 0) {
client[i] = connfd; /* save descriptor */
break;
}
if (i == FD_SETSIZE)
err_quit("too many clients");
FD_SET(connfd, &allset); /* add new descriptor to set */
if (connfd > maxfd)
maxfd = connfd; /* for select */
if (i > maxi)
maxi = i; /* max index in client[] array */
if (--nready <= 0)
continue; /* no more readable descriptors */
}
for (i = 0; i <= maxi; i++) { /* check all clients for data */
if ( (sockfd = client[i]) < 0)
continue;
**if (FD_ISSET(sockfd, &rset)) {
if ( (n = Read(sockfd, buf, MAXLINE)) == 0) {
/*4connection closed by client */
Close(sockfd);
FD_CLR(sockfd, &allset);
client[i] = -1;
} else
Writen(sockfd, buf, n);**
if (--nready <= 0)
break; /* no more readable descriptors */
}
}
}
}
About this program, Author said the server will suffer from DDOS attack as below:
enter image description here
the point is once a client request come, server read entire line then echo it. But is this code, we see server use Read function read data from client, not ReadLine or Readn, latters won't return until encounter a '\n' or fetch specified size data, but Read function immediately return in this case.
Read function just wrapper of system call "read" as below:
ssize_t Read(int fd, void *ptr, size_t nbytes)
{
ssize_t n;
if ( (n = read(fd, ptr, nbytes)) == -1)
err_sys("read error");
return(n);
}
So I confused why this server will suffer from a ddos attack?
Anyone can clarify it? Thank you very much!
I think that the confusion is due to a possible difference between the second edition and third edition of the book.
I have the 2nd edition and in it the "Read" is actually a "Readline". Then the explanation makes sense, due to the fact that Readline insists on reading until a newline.
I do not have a copy of the 3rd edition to compare with.
As for the explanation from Drunken Code Monkey, true, the read is blocking, however it is protected by the select which will guarantee that the read is only called if there is activity on the socket (either a disconnect, or at least 1 byte to read). So it is guaranteed that the read will not block. But see my explanation regarding if Read is replaced with Readline (as in 2nd edition)
See also a previous post on Stack Overflow Unix Network Programming Clarification
As per Stephane's response, here is an example to illustrate proper connection handling in a threaded TCP server. Note that I am not comfortable enough with linux development to write it easily, so this is C#, but the program flow should be the same. Treat it as pseudo-code if you must.
// We use a wait handle here to synchronize the client threads with the main thread.
private static AutoResetEvent _waitHandle = new AutoResetEvent(false);
static void Main(string[] args)
{
// Start the server on port 1337
StartServer(1337);
}
private static void StartServer(int port)
{
// Create a connection listener
var listener = new TcpListener(IPAddress.Any, port);
try
{
// Start the listener
listener.Start();
while (true)
{
// Wait for a connection, and defer connection handling asynchronously.
listener.BeginAcceptTcpClient(new AsyncCallback(HandleAsyncConnection), listener);
_waitHandle.WaitOne();
_waitHandle.Reset();
}
}
catch (SocketException ex)
{
// Handle socket errors or any other exception you deem necessary here
}
finally
{
// Stop the server.
listener.Stop();
}
}
private static void HandleAsyncConnection(IAsyncResult state)
{
// Get the listener and the client references
var listener = (TcpListener)state.AsyncState;
using (var tcpClient = listener.EndAcceptTcpClient(state))
{
// Signal the main thread that we have started handling this request.
// At this point the server is ready to handle another connection, and no amount
// of tomfoolery on the client's side will prevent this.
_waitHandle.Set();
// Declare buffers
var inBuff = new byte[tcpClient.ReceiveBufferSize];
var outBuff = new byte[tcpClient.SendBufferSize];
// Get the connection stream
using (var stream = tcpClient.GetStream())
{
try
{
// Read some data into inBuff
stream.Read(inBuff, 0, tcpClient.ReceiveBufferSize);
// Do something with the data here, put response in outBuff...
// Send response to client
stream.Write(outBuff, 0, outBuff.Length);
}
catch (SocketException ex)
{
// Handle socket errors or any other exception you deem necessary here
}
}
}
}
I have an LDR/Photocell which sends a value 1 or 0 (depending on the value) to a text file on my web address. The code works for a few seconds then prints out No Socket available.
Any help will be appreciated; code below.
#include <SPI.h>
#include <WiFi.h>
int LDR = A0;
int LED = 11;
char ssid[] = "SSID";
char password[] = "password";
int status = WL_IDLE_STATUS;
char server[] = "www.example.com";
int value;
void setup() {
Serial.begin(9600);
pinMode(LDR, INPUT);
pinMode(LED, OUTPUT);
connectWifi();
printWifiStatus();
// postData();
}
void loop() {
value = analogRead(LDR);
postData();
delay(10000);
}
void connectWifi() {
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to ");
Serial.println(ssid);
status = WiFi.begin(ssid, password);
delay(500);
}
}
void printWifiStatus() {
// Print the SSID of the network you're attached to
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// Print your WiFi shield's IP address
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// Print the received signal strength
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
void postData() {
WiFiClient client;
if (client.connect(server, 80)) {
Serial.println("Connecting...");
if (value > 350) {
Serial.println("0");
digitalWrite(LED, LOW);
String data = "value=0";
client.print("GET /example/client.php?");
client.print(data);
client.println(" HTTP/1.1");
client.println("Host: www.example.com");
client.println("Connection: close");
client.println(); client.println();
//client.stop();
} else {
Serial.println("1");
digitalWrite(LED, HIGH);
String data = "value=1";
client.print("GET /example/client.php?");
client.print(data);
client.println(" HTTP/1.1");
client.println("Host: www.example.com");
client.println("Connection: close");
client.println(); client.println();
//client.stop();
}
} else {
Serial.println("Connection failed");
client.stop();
}
}
Output:
Attempting to connect to SSID
SSID: SSID
IP Address: 255.255.255.255
signal strength (RSSI):-47 dBm
Connecting...
1
Connecting...
0
Connecting...
0
Connecting...
0
No Socket available
Connection failed
No Socket available
Connection failed
No Socket available
Connection failed
No Socket available
Actual web address omitted.
first of all, try not use "delay()" and your are calling this function "postData()" every 0,5 seconds. Try use the millis() function to do the timer thing, like this:
unsigned long timerBefore = 0;
const int timer = 1000; //1 second
now inside your loop()
unsigned long timerNow=millis();
if((unsigned long)(timerNow-timerBefore)>=timer){
postData();
timerBefore=millis();
}
that code i'll not "pause" your microcontroller and will call that function every one second.
I am using the select call and accepting the connection from "X" no of clients.
I made duplex connection i.e. server to client and client to server.
When connection is established between 2 entities ,I am going to send
data in chunks from one entity to other.
During send I read one file in chunks and send the data in chunks.
while(file_size !=0)
{
read_bytes = read(fd, buff, sizeof(buff));
cnt_ = send(_sock_fd,buff,actually_read,0);
file_size = file_size - cnt_;
printf("total sent remaining %d : %d\n",size,actually_read);
}
while at receiver side
//First I send the header which contain size it got accepted fine but during the following send call I used "get_readable_bytes" (Using ioctl) which returns me the no of bytes arrived at socket
`while(size != 0)
{
int test_ = 0;
while(((cnt_= get_readable_bytes(_sock_fd))== 0) )//&& test_ == 0
{
cnt_= get_n_readable_bytes(_sock_fd);
printf("Total bytes recved %d\n",cnt_);
//test_ = test_ + 1;
}
while(cnt_ != 0)
{
actually_read = recv(_sock_fd, buff, sizeof(buff),0);
int _cnt = get_n_readable_bytes(_sock_fd);
printf("Total bytes recved %d\n",cnt_-_cnt);
write(_fd,buff,actually_read);
cnt_ = cnt_ - actually_read;
test_ = 0;
}
`Now the problem is
1.During this execution of receive function control automatically go to the select function and it tries to execute whole receive function again so is there any way to synchronize the sender and receivers such that when the sender complete then start receiver or as soon as sender start receiver ?
2.And how do I maintain the count of bytes sent and received.
and this is my select call
`is_read_availble = select(maxfd + 1,&read_set,NULL,NULL,&timeout)`
with timeout 10sec.
Sketch of the kind of buffer code you need. (To allow partial reads/writes, the buffers need to be persistent between calls) BTW: you really need to handle the -1 return from read() and write() because they would seriously disturb your buffer-bookkeeping. EINTR + EAGAIN/EWOULDBLOCK is very common.
struct buff {
unsigned size;
unsigned bot;
unsigned top;
char *buff;
};
struct buff bf = {0,0,0,NULL};
initialisation:
bf.buff = malloc(SOME_SIZE);
/* ... error checking omitted */
bp.size = SOME_SIZE;
bp.bot = bp.top =0;
reading:
unsigned todo;
int rc;
/* (maybe) shift the buffer down to make place */
todo = bf.top - bf.bot;
if (todo) {
memmove (bf.buff, bf.buff + bf.bot, todo);
bf.top = todo; bf.bot = 0;
}
todo = bf.size - bf.top;
if (!todo) { /* maybe throttle? ... */ return; }
rc = read (fd, bf.buff+bp.top, todo);
/* ... error checking omitted */
if (rc == -1) switch (errno) {...}
else if (rc == 0) {...}
else {
total_read += rc;
bp.top += rc;
}
writing:
unsigned todo;
int rc;
todo = bf.top - bf.bot;
if (!todo) { /* maybe juggle fd_set ... */ return; }
rc = write (fd, bf.buff+bp.bot, todo);
/* ... error checking omitted */
if (rc == -1) switch (errno) {...}
else if (rc ==0) { ...}
else {
bp.bot += rc;
total_written += rc;
if (bp.bot == bp.top) bp.bot = bp.top =0;
}
/* ... this is the place to juggle the fd_set for writing */