C ++ closing first connection attempt

I am trying to create a sample server in C ++ using <sys/socket.h> and Qt Creator gui builder, but two strange behaviors occur at the socket level of the program. Firstly, I start the server, but the first time I try to connect to it using telnet closes immediately

Attempt 127.0.0.1 ...
Connected to 127.0.0.1.
The escape character is "^]".
Connection closed by foreign host.

When I try to connect a second time, it works and the terminal is waiting for input. Secondly, when I close the connection. If I re-run immediately, within a few minutes the program stops at bind , exiting and returning:

BINDING ERROR: address already in use

So, maybe the connection happens after I break it using the onCortarConexao() function call or just stopping the debugger. Anyway, what am I missing?

My code is:

 #include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } 

In MainWindow.cpp:

 void MainWindow::on_pushButton_clicked() { socket1 = new MSocket(); socket1->start(); } void MainWindow::on_pushButton_3_clicked() { socket1->onCortarConexao(); } 

Socket Class:

 #ifndef MSOCKET_H #define MSOCKET_H #include <QString> #include <QObject> #include <QThread> #include <QList> #include <string.h> #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #define SERVER_BUFFER 4096 #define PORTRUN 15000 class MSocket : public QThread { public: MSocket(); void error(char *msg); void onCortarConexao(); private: int sockfd; int newsockfd; int portno; int clilen; int n; char buffer[SERVER_BUFFER]; struct sockaddr_in serv_addr, cli_addr; u_short port; void run(); }; #endif // MSOCKET_H 

Socket Implementation:

 void MSocket::run() { sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0){ error("ERROR opening socket"); exit(-1); } bzero((char *) &serv_addr, sizeof(serv_addr)); portno = PORTRUN; serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(portno); serv_addr.sin_addr.s_addr = INADDR_ANY; fprintf(stdout,"Iniciando servidor.."); if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){ error("ERROR on binding"); exit(-1); } listen(sockfd,5); newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t*) sizeof(cli_addr)); if (newsockfd < 0){ error("ERROR on accept"); exit(-1); } bzero(buffer,SERVER_BUFFER); n = read(newsockfd,buffer,SERVER_BUFFER-1); if (n < 0) error("ERROR reading from socket"); printf("Here is the message: %s",buffer); n = write(newsockfd,"I got your message",18); if (n < 0) error("ERROR writing to socket"); } void MSocket::onCortarConexao(){ printf("Encerrando socket"); close(newsockfd); close(sockfd); } 

Full code: https://github.com/FabioNevesRezende/BasicCppServer

Change 1:

So this is a list of communication packages between telnet and my Qt Server application, it can be graphically seen in WireShark (.pcapng file). It contains 11 frames. The first 6 of the first telnet when it is immediately closed. As it seems in frames 4 and 5, where the application sends [FIN, ACK] , and the server responds to it, closing the connection. Frames 7,8,9 are the second connection attempt, and frames 10 and 11 are when abc sent to the server. As on the print screen:

sequence of commands

The problem is that I do not know why the application sends this FIN and where it is in the code.

+5
source share
4 answers

Use SO_REUSEADDR with setsockopt :

 optval = 1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval); 

This allows the port to be reused by other sockets and bypasses the address already in use problem you are facing.

+4
source

The previous answers indicate how to handle the reading correctly and how to use SO_RESUEADDR. I want to indicate why your program can simply receive one message. because your start function does not have a loop, so it can only be executed once, then the thread exits. after accepting the clientโ€™s request, then the connection is established, then you must enter a loop to wait for the clientโ€™s input and write them after the read function returns.

+5
source

Here is the first serious problem I found:

 n = read(newsockfd,buffer,SERVER_BUFFER-1); if (n < 0) error("ERROR reading from socket"); printf("Here is the message: %s",buffer); 

There is no processing for read returning zero. The %s format specifier is for strings only. You cannot use it for arbitrary, unverified data.

+3
source

On Unix operating systems, system calls can sometimes fail with errno set to EINTR. This means that the signal was passed to the process that interrupted the system call, and you must repeat it. Try something like this:

 while ((n = read(newsockfd,buffer,SERVER_BUFFER-1) < 0) { if (errno != EINTR) break; } if (n < 0) error("ERROR reading from socket"); 

The same must be done for the call to record.

+3
source

All Articles