I have server client application.
When I'm sending messages in a row(without scanf in the code below), it's seems the server doesn't get them(doesn't print).
if I wait a little bit(with the scanf in the code below) and then send the next message the server works fine and prints all messages.
what's the problem?
how can I fix it, cause I want to do more with the message(not just to print it) that arrived to the server.
in my client code(where server prints nothing)
char message[(100)] = {0};
int x = rand();
while(i < 3)
{
printf(" I send %d\n", x);fflush(NULL);
sprintf(message, "%d",x);
if( send(mainSockfd, message,strlen(message),0) == -1)
{
printf("ERRRRRORRRR\n");fflush(NULL);
}
i++;
x = rand() % 100;
}
in my client code(when server prints the messages)
char message[(100)] = {0};
int x = rand();
while(i < 3)
{
printf(" I send %d\n", x);fflush(NULL);
sprintf(message, "%d",x);
if( send(mainSockfd, message,strlen(message),0) == -1)
{
printf("ERRRRRORRRR\n");fflush(NULL);
}
i++;
x = rand() % 100;
scanf("%d",&x); // this is the only change
}
in my server code
char command[(100+1)] = {0};
while(1)
{
readLength = recv(sockfd, command, 100+1,0);
if(readLength > 0)
{
printf("arrived = %s,\n",command);fflush(NULL);
ZeroMemory(command, sizeof(command));
}
else if( readLength == 0)
{
break;
}
else if ( readLength < 0 ){
if(GetLastError() == 10035)
{
continue;
}
if(GetLastError() == 10057 || GetLastError() == 10054)
{
break;
}
continue;
}
}
As you seem to be transferring 0-terminated "strings" without the 0 termination, you should read one char less then the read buffer provides to always have the read buffer being 0-terminated, as if you try to printf a non 0-terminated "string" you provoke undefined behaviour.
So change this
readLength = recv(sockfd, command, 100+1,0);
to become this
readLength = recv(sockfd, command, 100,0);
Related
I'm working on a C program to solve the Dining Philosophers' problem. I loop through 500 philosopher state changes, and output each philosophers' status on each interation with the following statement:
printf(" %d> |%s|%s|%s|%s|%s \n", i, get_state(phils[0]), get_state(phils[1]), get_state(phils[2]), get_state(phils[3]), get_state(phils[4]));
For context, here is the function get_state, which converts a numeric philosopher status into a string:
char * get_state(int t) {
if (t == 1)
return " Thinking ";
if (t == 2)
return " Hungry ";
if (t == 3)
return " Eating ";
return "----Error----";
}
My problem is this: every 5-30 lines, one of them will start with the unicode character U+0001. It appears that it is probably being inserted after the \n of the previous line, but I can't tell what causes it at all!
I've provided a screenshot for clarity:
And here is the whole loop:
for (i = 1; i <= MAX; i++) {
silent = 0;
// receive message from child node
for (j = 0; j < PHIL_NO; j++) {
if(phils[j] == EATING) {
count[j]++;
}
lastPhils[j] = phils[j];
};
read(host[READ], &msg, sizeof(msg));
phils[msg.index] = msg.state;
for (j = 0; j < PHIL_NO; j++) {
if (phils[j] == lastPhils[j])
{
silent++;
}
};
printf("%4d> |%s|%s|%s|%s|%s \n", i, get_state(phils[0]), get_state(phils[1]),
get_state(phils[2]), get_state(phils[3]), get_state(phils[4]));
// if message is "hungry"
if (msg.state == HUNGRY) {
state_left = 0;
state_right = 0;
// check if chopsticks are available
if (phils[(msg.index - 1)%PHIL_NO] == EATING) {
state_left = 1;
}
if(phils[(msg.index + 1)%PHIL_NO] == EATING) {
state_right = 1;
}
// if available...
if (state_left+state_right == 0) {
// send message EATING to node
msg.state = EATING;
write(node[msg.index][WRITE], &msg, sizeof(msg));
} else {
// make the node wait
write(node[msg.index][WRITE], &msg, sizeof(msg));
}
} else if (msg.state == THINKING) {
// awake neighborhood nodes to eat
write(node[(msg.index-1)%PHIL_NO][WRITE], &msg, sizeof(msg));
write(node[(msg.index+1)%PHIL_NO][WRITE], &msg, sizeof(msg));
}
};
Edit: Oddly enough, when I run it in XTerm I can't see the extra character. I think that just means that XTerm doesn't display it. At this point, I'm pretty sure #Barmar is right in assuming it's one of my pipe write()s misbehaving.
It's my first post so ask for remotely anything if it can help and I didn't provide it.
My application requires multiple sockets being opened at once from Master, then the slaves connect to WiFi, and then to the sockets
Problem is: I have to make it "bulletproof" against constant reconnecting from slaves and i get Accept error:
E (23817) TCP SOCKET: accept error: -1 Too many open files in system
It appears when I reconnect client for 5th time, when Max Number of Open Sockets = 5 in menuconfig,
I disconnect clients from the server when they don't send anything in 1second -> then i assume they got DC-d.
I do it with close() procedure.
void closeOvertimedTask(void * ignore)
{
while(1)
{
for(int i = 0; i < openedSockets;)
{
if(needsRestart[i] == 1)
{
ESP_LOGI("RESTARTING", " task#%d",i);
//lwip_close_r(clientSock[i]);
//closesocket(clientSock[i]);
//ESP_LOGI("closing result", "%d", close(clientSock[i]));
stopSocketHandler(i);
needsRestart[i] = 0;
//if(isSocketOpened[i])
{
}
ESP_LOGI("close", "%d", lwip_close_r(clientSock[i]));
isSocketOpened[i] = 0;
xTaskCreate( handleNthSocket, "TCP_HANDLER", 10*1024, &(sockNums[i]) , tskIDLE_PRIORITY, &socketHandlerHandle[i]);
configASSERT(socketHandlerHandle[i]);
needsRestart[i] = 0;
}
if(isSocketOpened[i])
{
int diff = ((int)((uint64_t)esp_timer_get_time()) - lastWDT[i]) - 2*TCPWDT;
if(diff > 0)
{
if(isSocketOpened[i])
{
ESP_LOGI("I FOUND OUT HE DC-d","");
//closesocket(clientSock[i]);
}
ESP_LOGI("close", "%d", close(clientSock[i]));
stopSocketHandler(i);
isSocketOpened[i] = 0;
xTaskCreate( handleNthSocket, "TCP_HANDLER", 10*1024, &(sockNums[i]) , tskIDLE_PRIORITY, &socketHandlerHandle[i]);
configASSERT(socketHandlerHandle[i]);
}
}
}
}
}
For each socket I run 1 task that is supposed to receive from that socket and act further.
For all of them I have an other task that checks last time a message arrived and restarts tasks when time has exceeded (it's 2 seconds)
I need around 16 sockets opened in the final version so there is no room to have sockets that are still closing after Slave has restarted whole connection
How to properly close a Task with running recv() procedure in it to properly close Socket.
Is there a way to read from Server side that socket has been closed if WiFi hasn't realized STA DC-d
Is this about TIME_WAIT from tcp stack ?
Socket read code:
void handleNthSocket(void * param) // 0 <= whichSocket < openedSockets
{
int whichSocket = *((int *) param);
ESP_LOGI("TCP SOCKET", "%s #%d", getSpaces(whichSocket), whichSocket);
struct sockaddr_in clientAddress;
while (1)
{
if(needsRestart [whichSocket] == 0)
{
socklen_t clientAddressLength = sizeof(clientAddress);
clientSock[whichSocket] = accept(sock[whichSocket], (struct sockaddr *)&clientAddress, &clientAddressLength);
if (clientSock[whichSocket] < 0)
{
ESP_LOGE("TCP SOCKET", "accept error: %d %s", clientSock[whichSocket], strerror(errno)); //HERE IT FLIPS
//E (232189) TCP SOCKET: accept error: -1 Too many open files in system
isSocketOpened[whichSocket] = 0;
needsRestart[whichSocket] = 1;
continue;
}
//isSocketOpened[whichSocket] = 1;
// We now have a new client ...
int total = 1000;
char dataNP[1000];
char *data;
data = &dataNP[0];
for(int z = 0; z < total; z++)
{
dataNP[z] = 0;
}
ESP_LOGI("TCP SOCKET", "%snew client",getSpaces(whichSocket));
ESP_LOGI(" ", "%s#%d connected",getSpaces(whichSocket), whichSocket);
lastWDT[whichSocket] = (uint64_t)esp_timer_get_time() + 1000000;
isSocketOpened[whichSocket] = 1;
// Loop reading data.
while(isSocketOpened[whichSocket])
{
/*
if (sizeRead < 0)
{
ESP_LOGE(tag, "recv: %d %s", sizeRead, strerror(errno));
goto END;
}
if (sizeRead == 0)
{
break;
}
sizeUsed += sizeRead;
*/
ssize_t sizeRead = recv(clientSock[whichSocket], data, total, 0);
/*for (int k = 0; k < sizeRead; k++)
{
if(*(data+k) == '\n')
{
ESP_LOGI("TCP DATA ", "%sthere was enter", getSpaces(whichSocket));
//ESP_LOGI("TIME ", "%d", (int)esp_timer_get_time());
}
//ESP_LOGI("last wdt", "%d", (int)lastWDT[whichSocket]);
}*/
lastWDT[whichSocket] = (uint64_t)esp_timer_get_time();
int diff = ((int)((uint64_t)esp_timer_get_time()) - lastWDT[whichSocket]) - 2*TCPWDT;
ESP_LOGI("last wdt", "%d, data = %s", (int)lastWDT[whichSocket], data);
if(diff > 0)
{
ESP_LOGI("last wdt", "too long - %d", diff);
isSocketOpened[whichSocket] = 0;
}
if (sizeRead < 0)
{
isSocketOpened[whichSocket] = 0;
}
//TODO: all RX from slave routine
for(int k = 0; k < sizeRead; k++)
{
*(data+k) = 0;
}
// ESP_LOGI("lol data", "clientSock[whichSocket]=%d,
/*if(sizeRead > -1)
{
ESP_LOGI("TCP DATA: ", "%c", *(data + sizeRead-1));
}
else
{
ESP_LOGI("TCP DC ", "");
goto END;
}*/
}
if(isSocketOpened[whichSocket])
{
ESP_LOGI("closing result", "%d", close(clientSock[whichSocket]));
}
}
}
}
I don't see you closing your sockets anywhere?
Sockets, no matter the platform, is usually a limited resource, and a resource that will be reused. If you don't close the sockets then the system will think that you still use then, and can't reuse those sockets for new connections (and on POSIX systems even opening files will be affected).
So close connections immediately when they are not needed any more.
Usually this is done by checking what recv and send returns: If they return a value less than zero an error occured and in most cases it's a non-recoverable errors, so connection should be closed. Even if it is a recoverable error, it's easier to close the connection and let the client reconnect.
For recv there's also the special case when it returns zero. That means the other end has closed the connection. That of course you need to close your end as well.
this post solved all my problems
https://www.esp32.com/viewtopic.php?t=911
Fairly new to socket programming, so here goes my question. What is wrong? What my function does, is take input from the telnet session and then when you press 'enter' it should go break the while loop. But it doesn't for some reason. I can't figure out why either, I've tried various ways but, nothing I've tried thus far worked yet.
void handle_clients(socket,address)
int *socket;
const char *address;
{
char msg[256];
char cmd[128];
int bytes;
memset(msg,0,sizeof(msg));
memset(cmd,0,sizeof(cmd));
while(1) {
send(*socket,"CMD >> ",7,0);
bytes = 0;
while((bytes = recv(*socket,cmd,sizeof(cmd),0)) > 0) {
if(bytes < 0) {
sprintf(msg,"Error: receiving from %s.\r\n",
address);
send(*socket,msg,strlen(msg),0);
break;
}
if(cmd[bytes] == 10 || cmd[bytes] == 13) {
break;
}
}
if(strcmp(cmd,"exit") == 0) {
break;
} else if(strcmp(cmd,"help") == 0) {
sprintf(msg,"Commands: [exit,cmd,help]\r\n");
send(*socket,msg,strlen(msg),0);
} else if(strcmp(cmd,"cmd") == 0) {
memset(cmd,0,sizeof(cmd));
send(*socket,"Enter command: ",15,0);
bytes = 0;
while((bytes = recv(*socket,cmd,sizeof(cmd),0)) > 0) {
if(bytes < 0) {
sprintf(msg,"Error: receiving from %s.\r\n",
address);
send(*socket,msg,strlen(msg),0);
break;
}
if(cmd[bytes] == 10 || cmd[bytes] == 13) {
break;
}
}
system(cmd);
} else {
sprintf(msg,"Unknown command.\r\n");
send(*socket,msg,strlen(msg),0);
}
memset(msg,0,sizeof(msg));
memset(cmd,0,sizeof(cmd));
}
}
it should go break the while loop. But it doesn't for some reason.
In addition to the issues pointed out by my peers, I think the answer to your specific inquiry lies in the nested while loops and the missing \r\n chars from the strcmp.
Since the while loops are nested, than break might break the nested loop while the container loop remains - so you're back in the next nested loop in your next iteration.
For example:
while(1) {
send(*socket,"CMD >> ",7,0);
bytes = 0;
while((bytes = recv(*socket,cmd,sizeof(cmd),0))) {
if(bytes < 0) {
sprintf(msg,"Error: receiving from %s.\r\n",
address);
send(*socket,msg,strlen(msg),0);
break; /* <= WHICH LOOP ARE WE BREAKING? */
}
if(cmd[bytes] == 10 || cmd[bytes] == 13) {
break; /* <= WHICH LOOP ARE WE BREAKING? */
}
}
// ...
}
This is one of those cases where goto might be your friend...
...although I do think there are better and more elegant solutions and changes that might be required to your code before you go there.
Also, What's the point of re-reading the data, if you're overwriting the existing buffer?
I find it almost (in this case) more convenient and likely to ignore the possible case of incomplete TCP/IP packets/commands.
In this specific case, it seems okay to assume that if the command doesn't end with a new line, something is wrong and we can disconnect. Such short commands should pass in a single TCP/IP packet. i.e.:
while(1) {
send(*socket,"CMD >> ",7,0);
bytes = 0;
bytes = recv(*socket,cmd,sizeof(cmd),0);
if(!bytes) { // closed by peer
close(*socket);
return;
}
if(bytes < 0 || cmd[bytes-1] == 10 || cmd[bytes-1] == 13) {
if(errno == EINTR)
continue;
sprintf(msg,"Error: receiving from %s.\r\n",
address);
close(*socket);
return;
}
if(strcmp(cmd,"exit\r\n") == 0) {
break;
} else if(strcmp(cmd,"help\r\n") == 0) {}
// ...
}
This code obviously ignores the possibility of multiple commands being read in a single recv (i.e., the buffer being "help\r\ncmd\r\nX\r\nexit\r\n")... but you'll solve that at some point.
This has a logic problem:
while((bytes = recv(*socket,cmd,sizeof(cmd),0)) > 0) {
if(bytes < 0) {
}
}
bytes will be always greater than zero so the if(bytes<0){} block will never
execute.
You may want to change it to
while((bytes = recv(*socket,cmd,sizeof(cmd),0))) {
if(bytes < 0) {
}
}
If bytes equals to zero, it will not enter while loop.
I am implementing the tiny server, and have a trouble to detect the client request. The requirement require that we only accept the client's request if there are two consecutive CRLFs. So my current code is:
int bytes_read = recv(client, buffer, sizeof(buffer), 0);
if (bytes_read < 0) {
printfError("Problem with recv call", false);
}
if(checkRequest(buffer)) {
// Accept client's request
}
In my checkRequest, I will check the client's request method, filename, and HTTP:
bool checkRequest(char *buff, int &valid, int &ext) {
char *request_method = strtok(buff, " ");
char *request_filename = strtok(NULL, " ");
char *request_http = strtok(NULL, " ");
int i;
bool isValid = false;
for(i = 0; i < 2; i++) {
if(*request_http == '\r') {
isValid = true;
*request_http++;
if(*request_http == '\n') {
// Keep checking
*request_http++;
} else {
isValid = false;
}
}
if(!isValid) break; // Not 2 consecutive CRLFs;
}
return isValid;
The problem that I have when testing on telnet is when I hit the first enter; it is only able to detect the first crlf. I also try to but the recv() between the while loop but it will stuck inside it.
Although there are more thorough and robust ways to achieve this, this is the simple solution to your problem. There is never any guarantee how many bytes you will receive from the senders call so you must keep calling recv until you've got the quantity of data you expect.
const unsigned int kuiBytesExpected = 4;
unsigned int uiBytesReceived = 0;
while ( uiBytesReceived < kuiBytesExpected )
{
int bytes_read = recv(client, buffer + uiBytesReceived, kuiBytesExpected - uiBytesReceived, 0);
// recv returns 0 if client disonnects and -1 on error
if ( bytes_read < 1 )
{
printfError("Problem with recv call", false);
break;
}
else
{
uiBytesReceived += bytes_read;
}
}
if ( uiBytesReceived == kuiBytesExpected )
{
if(checkRequest(buffer))
{
// Accept client's request
}
}
I am trying to send data through a Tcp connection using C.
I am able to send data properly , but when I close the client side application (CTRL-C), the loop in the server side runs infinitely.
Can anyone explain me what I am doing wrong ? What can I do to prevent it?
//Server-Side code.
while (TRUE)
{
accepted_socket = accept(connection_socket, (struct sockaddr*)0, 0) ;
if(accepted_socket < 0 )
{
perror("accept function in main() ") ;
close(connection_socket) ;
exit(1) ;
}
do
{
int recieved_bytes = recv(accepted_socket, &buff,1, 0) ; // it will store the recieved characters inside the buff.
if(recieved_bytes < 0 )
{
perror("Error occurred ! Recieved bytes less than zero. in mainloop.") ;
}
printf("%c", buff) ;
}
while(buff!= ' ') ; // This loop runs infinitely.
}
//Client Side-Code
char c = 'c' ;
do
{
c = getchar() ;
if(send(*connection_socket, &c, 1, 0) < 1 )
{
if(errno == ECONNRESET)
{
fprintf(stderr, "Your message couldn't be sent, since connection was reset by the server.\n") ;
exit(1) ;
}
perror("Not all bytes sent in send() in main()") ;
}
}
Your server code runs in 2 loops: the outer one waits for more connections, and as soon as you have a connection, it goes on running.
There is currently no reason to terminate one of them. If you want to terminate the inner one, you should additionally check for the result value being == 0, meaning the end of the connection.
Even if you do
while (TRUE)
{
accepted_socket = accept(connection_socket, (struct sockaddr*)0, 0);
if (accepted_socket < 0)
{
perror("accept function in main() ");
close(connection_socket);
exit(1);
}
// here starts the loop for the accepted_socket:
do
{
int recieved_bytes = recv(accepted_socket, &buff,1, 0); // it will store the recieved characters inside the buff.
if(recieved_bytes < 0)
{
perror("recv");
}
size_t i;
for (i=0; i < received_bytes; i++) printf("%c", buff[i]);
} while(received_bytes != 0);
}
your outer loop goes on running.