I'm also facing some issue where a server sends data to client and client sends back the acknowledgement. But after certain iterations the socket is aborted and I'm getting WSAECONNABORTED (10053) while sending the acknowledgement back to server.
I'm on win7 64-bit machine.
Server code(this is perl code):
sub Send_Msg_to_SourceSelector
{
(my $msg)=#_;
my $msg_len = length("$msg")+1;
print "the message length is: $msg_len\n\n";
PrintLogFile(1, ">> $CurrentTime >> The message length is : $msg_len <<<<\n\n");
print "the SOCK1 is: SOCK\n\n";
PrintLogFile(1, ">> $CurrentTime >> The sent message is : $msg <<<<\n\n");
send $SOCK,$msg,$msg_len;
print "the SOCK2 is: $SOCK\n\n";
recv $SOCK,my $awk,3,0;
PrintLogFile(1, ">> $CurrentTime >> The acknowledgement received is : $awk <<<<\n\n");
print "the SOCK3 is: $SOCK\n\n";
}
Client code (this is in C...executable generated in visual studio 2013):
void RecvDataFromSequencer(SOCKET sock, FILE *Log)
{
char n,buffer[2000];
while(!FlagTestExecutionCompleted)
{
memset (buffer , 0 , 2000);
printf("The address of buffer before is: %d\n", buffer);
n = recv(sock,buffer,2000,0); //blocking call
printf("The address of buffer after is: %d\n", buffer);
printf("in recv func: %x\n", Log);
//printlogfile(Log, buffer);
fprintf(Log,"%s%s",buffer,"\n");
fprintf(Log,"%d%s",n,"\n");
fprintf(Log,"%s%d%s","FlagTestExecutionCompleted is ==> ",FlagTestExecutionCompleted,"\n");
fflush(Log);
if (n == -1)
{
printf("recv failed: %d\n", WSAGetLastError());
fprintf(Log,"%s%s",WSAGetLastError(),"\n");
error("ERROR reading from STATS");
fprintf(Log,"%s%s","ERROR reading from STATS","\n");
fflush(Log);
}
else
{
printf("\nMessage from STATS: %s\n",buffer);
strcpy(line_tcfile,buffer);
if(strstr(line_tcfile,"SessionCompleted"))
{
printf("\n End of Test Session");
FlagTestExecutionCompleted=1;
}
FlagNewTestCaseRecieved = 1;
}
//Send acknowledgement
Sleep(1000);
**n = send(sock,"ACK",3,0);
if (n == -1)
{
fprintf(Log,"%s%d%s","in send command FlagTestExecutionCompleted is ==> ",FlagTestExecutionCompleted,"\n");
printf("send failed: %d\n", WSAGetLastError());
fprintf(Log,"%s%s",WSAGetLastError(),"\n");**
fprintf(Log,"%s%s","ERROR writing to STATS","\n");
fprintf(Log,"%d%s",n,"\n");
fflush(Log);
error("ERROR writing to STATS");
}
In this the following is happening:
1. server reads a line and sends to client
2. client reads the line and sends back the acknowledgement back to server
3. this process happens successfully to some tests
4. after some time the while sending back acknowledgement to server through send command, it returns WSAECONNABORTED (10053)
I don't know what is the reason.
Please help
Thanks,
Pankaj
Related
We are using libmodbus library to read register values from energy meter EM6400 which supports Modbus over RTU. We are facing the following two issues.
1) We are facing an issue with modbus_read_registers API, this API returns -1 and the error message is:
ERROR Connection timed out: select.
After debugging the library, we found this issue is due to the echo of request bytes in the response message.
read() API call in _modbus_rtu_recv returns request bytes first followed by response bytes. As a result, length_to_read is calculated in compute_data_length_after_meta() based on the request bytes instead of response bytes (which contains the number of bytes read) and connection timed out issue occurs.
We tried to use both 3.0.6 and 3.1.2 libmodbus versions but same issue occurs in both the versions.
2) modbus_rtu_set_serial_mode (ctx, MODBUS_RTU_RS485) returns "BAD file descriptor".
Please confirm if there is any API call missing or any parameter is not set correctly.
Our sample code to read register value is as follows.
int main()
{
modbus_t *ctx;
uint16_t tab_reg[2] = {0,0};
float avgVLL = -1;;
int res = 0;
int rc;
int i;
struct timeval response_timeout;
uint32_t tv_sec = 0;
uint32_t tv_usec = 0;
response_timeout.tv_sec = 5;
response_timeout.tv_usec = 0;
ctx = modbus_new_rtu("/dev/ttyUSB0", 19200, 'E', 8, 1);
if (NULL == ctx)
{
printf("Unable to create libmodbus context\n");
res = 1;
}
else
{
printf("created libmodbus context\n");
modbus_set_debug(ctx, TRUE);
//modbus_set_error_recovery(ctx, MODBUS_ERROR_RECOVERY_LINK |MODBUS_ERROR_RECOVERY_PROTOCOL);
rc = modbus_set_slave(ctx, 1);
printf("modbus_set_slave return: %d\n",rc);
if (rc != 0)
{
printf("modbus_set_slave: %s \n",modbus_strerror(errno));
}
/* Commented - Giving 'Bad File Descriptor' issue
rc = modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
printf("modbus_rtu_set_serial_mode: %d \n",rc);
if (rc != 0)
{
printf("modbus_rtu_set_serial_mode: %s \n",modbus_strerror(errno));
}
*/
// This code is for version 3.0.6
modbus_get_response_timeout(ctx, &response_timeout);
printf("Default response timeout:%ld sec %ld usec \n", response_timeout.tv_sec, response_timeout.tv_usec );
response_timeout.tv_sec = 60;
response_timeout.tv_usec = 0;
modbus_set_response_timeout(ctx, &response_timeout);
modbus_get_response_timeout(ctx, &response_timeout);
printf("Set response timeout:%ld sec %ld usec \n", response_timeout.tv_sec, response_timeout.tv_usec );
/* This code is for version 3.1.2
modbus_get_response_timeout(ctx, &tv_sec, &tv_usec);
printf("Default response timeout:%d sec %d usec \n",tv_sec,tv_usec );
tv_sec = 60;
tv_usec = 0;
modbus_set_response_timeout(ctx, tv_sec,tv_usec);
modbus_get_response_timeout(ctx, &tv_sec, &tv_usec);
printf("Set response timeout:%d sec %d usec \n",tv_sec,tv_usec );
*/
rc = modbus_connect(ctx);
printf("modbus_connect: %d \n",rc);
if (rc == -1) {
printf("Connection failed: %s\n", modbus_strerror(errno));
res = 1;
}
rc = modbus_read_registers(ctx, 3908, 2, tab_reg);
printf("modbus_read_registers: %d \n",rc);
if (rc == -1) {
printf("Read registers failed: %s\n", modbus_strerror(errno));
res = 1;
}
for (i=0; i < 2; i++) {
printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
}
avgVLL = modbus_get_float(tab_reg);
printf("Average Line to Line Voltage = %f\n", avgVLL);
modbus_close(ctx);
modbus_free(ctx);
}
}
Output of this sample is as follows:
created libmodbus context
modbus_set_slave return: 0
modbus_rtu_set_serial_mode: -1
modbus_rtu_set_serial_mode: Bad file descriptor
Default response timeout:0 sec 500000 usec
Set response timeout:60 sec 0 usec
Opening /dev/ttyUSB0 at 19200 bauds (E, 8, 1)
modbus_connect: 0
[01][03][0F][44][00][02][87][0A]
Waiting for a confirmation...
ERROR Connection timed out: select
<01><03><0F><44><00><02><87><0A><01><03><04><C4><5F><43><D4><C6><7E>modbus_read_registers: -1
Read registers failed: Connection timed out
reg[0]=0 (0x0)
reg[1]=0 (0x0)
Average Line to Line Voltage = 0.000000
Issue 1) is probably a hardware issue, with "local echo" enabled in your RS-485 adapter. Local echo is sometimes used to confirm sending of data bytes on the bus. You need to disable it, or find another RS-485 adapter.
I have written about this in the documentation of my MinimalModbus Python library: Local Echo
It lists a few common ways to disable local echo in RS-485 adapters.
This question already has answers here:
why socket on the receiving peer keep receiving '' infinitely when I use "control-c" to close the socket on the sending peer
(2 answers)
Closed 7 years ago.
Questions:
1. why socket recv keeps receiving data in a while loop, even if I don't send any data from sender? isn't recv() a blocking function, I thought it blocks until tcp receives some data; 2. why numbytes = 0 ?
Below is the code, I just post the code of recv() and send(), I think other parts of the code works fine, but if you need all code to debug, please let me know I'll post them, Thanks!
while(1) { //client receiving code
if ((numbytes = recv(sockfd, buf, MAXDATASIZE, 0)) == -1)
perror("recv");
}
buf[numbytes] = '\0';
printf("numbytes is %d\n", numbytes);
printf("client: received '%s'\n", buf);
}
while(1) { //server sending code
char str[100];
sin_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
perror("accept");
continue;
}
inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s);
printf("server: got connection from %s\n", s);
while(1) {
printf( "Enter a value :");
scanf("%s", str);
if (send(new_fd, str, 50, 0) == -1)
perror("send");
}
}
Below is the screenshot of the result:
Input on the server terminal
Enter a value :123456
Output on the client terminal
numbytes is 0
client: received '12345'
numbytes is 0
client: received '6'
numbytes is 0
client: received ''
numbytes is 0
client: received ''
numbytes is 0
client: received ''
numbytes is 0
client: received ''
numbytes is 0
client: received ''
numbytes is 0
client: received ''
numbytes is 0
client: received ''
numbytes is 0
client: received ''
Because you're ignoring the possibility of a zero return from recv(), which means the peer has closed the connection, which means you must do so too, and stop reading.
I want to send several files from Server to the Client but I'm having a problem.
Server sendfile code:
while ((len = fread(Buffer,1,sizeof(Buffer), fs)) > 0)
{
if((resultEnviar = send(ClientSocket,Buffer,len,0)) < 0){
printf("ERROR: Failed to send file %s.\n", nombreArchivoADescargar.c_str());
break;
}
sumEnviada+=resultEnviar;
}
fclose(fs);
Client receiveFile code:
//shutdown(sock, SD_SEND); ???????
do{
recvVal = recv(sock, Buffer2, sizeof(Buffer2), 0);
if (recvVal <= 0){
printf("Can't read from socket");
recvVal =0;
fclose(fp);
continue;
}else{
int off =0;
do{
int write_sz = fwrite(Buffer2, 1, recvVal, fp);
if (write_sz < 0){
printf("Can't write to file");
fclose(fp);
break;};
if (write_sz == 0) {cout<<endl<<"Nada que copiar"<<endl; break;}
off += write_sz;
}while(off<recvVal);
bzero(Buffer2, 1024);
contador+=off;
}
}while (contador<LongitudArchivo);
cout<<endl<<"Numero de bytes recibidos: "<<contador<<endl<<endl;
printf("Ok received from client!\n");
fclose(fp);
If I don't use the SHUTDOWN(sock, SD_SEND) I don't receive all the expected bytes but if I use it I don't know how to send more files (how to wake up the send part of the socket).
Thanks!
I don't see what shutdown() has to do with it. You should receive all the bytes either way. If you want to send multiple files, you will have to send the length ahead of each one and read exactly that many following bytes from the socket into each target file.
NB If recv() returns zero you should close the socket and break. If it returns -1 you should log the errno, e.g. via perror(), close the socket, and break.
I am trying to send the contents of a file from the server to the client , I am reading the file line by line using fgets and writing to the socket descriptor line by line , on the client side , i am in an a while loop , reading the sent contents.I am not being able to terminate the server sending sequence , i.e the client keeps reading the buffer and the next program line is not executed , I think thers something wrong with my way of sending or recieving . here is the code :
server :
filefd = fopen("clients.txt","a+");
while(fgets(filcont,300,filefd) != NULL)
{// write whole file contents to client
n=write(newsockfd,filcont,strlen(filcont));
if(n==0) break;
memset(filcont,'\0',300);
}
fclose(filefd);
client side :
while(n>0){
n = read(sockfd,buffer,sizeof(buffer)-1);
if(n==0) break;
printf("%s\nbytes read :%d \n",buffer,n);
memset(buffer,'\0',256);
}
printf("Enter peer name ( except yours ) to send connection request : \n");
the above line ( printf , peer name doesnot get executed until i terminate the server)
I was able to figure it out , I sent the file contents from the server using fread instead of fgets ( line by line ) and used a single read() at the client . this was the quick fix.
But I also figured out another technique when in case you have to compulsorily use fgets , where the while loop at the client side makes the socket nonblocking for read and then blocking again , the code is pasted below.
flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
while(n>0){
n = read(sockfd,buffer,sizeof(buffer)-1);
if(n==0) break;
if(n==-1) printf("\nNon blocking read failed congrats");
printf("%s\n",buffer);
memset(buffer,'\0',256);
}
printf("\nbytes read :%d \n",n);
val = fcntl(sockfd, F_GETFL, 0);
flags = O_NONBLOCK;
val &= ~flags; // makes it blocking again
fcntl(sockfd,F_SETFL,val);
The code from stackoverflow was refered to make the socket blocking
I'm using SO_REUSEADDR option, but I'm not sure why am getting
Resource temporary unvailable option.
I'm testing client server code on 127.0.0.1
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 )
{
perror("socket() error!!\n");
exit(1);
}
if ( setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse) ) < 0 ) {
perror("SO_REUSEADDR failed::");
exit(1);
}
while(1) {
nbytes_read = recvfrom(sockfd, (void *)&recvd_msg, sizeof(recvd_msg),
flags, &from, &from_len);
printf("nbytes_read = %d\n", nbytes_read);
if(nbytes_read == -1) {
perror("client: recvfrom() failed");
return FAILED;
}
if (nbytes_read > 0) {
if(recvd_msg.hdr.msgtype == DATA)
printf("recvd %d bytes from server\n", recvd_msg.hdr.payload_size);
ftp_show_payload(&recvd_msg);
}
if(recvd_msg.hdr.is_last == TRUE) {
break;
}
}
Error message:
" client: recvfrom() failed: Resource temporarily unavailable"
errno:11
After trying to run client for 3-4 times, I get the data, I'm not sure whats happening.
Also, this problem is on Ubuntu Linux, but when I run the same client server on Solaris,
it works fine!!
SO_REUSEADDR is useful when you use bind(), but here you are not using bind.
I dont see any problem if recvfrom() returns -1
Use bind() and replace your call recvfrom() with recv(). recv() will receive all the packets at the port you used in your bind call.
Are you trimming out any other socket configuration? EAGAIN is typically returned when you read a non-blocking socket and there's no data available. The manpage for recvfrom lists the possible errnos that will be set on failure with an explanation for each one.
Your test is invalid. recvfrom() can return zero, which doesn't indicate an error. It is only valid to call perror() if you get -1. So you may not have a problem at all ..
I don't see why you're using SO_REUSEADDR at all here, as you're not binding to a specific port.