0
votes

I've got a program and it's listening on port 200. After a client is connected to it, all the received data from client is written to std::cout. If any error occures while getting data from client, I would like to restart hosting.

ServerSocket sock;
while(true)
{
    try
    {
        uint8 buff[1000];
        std::cout << "hosting..." << std::endl;
        sock.Host(port);

        while(true)
        {
            size_t ret = sock.GetData(buff, 1000);
            buff[ret] = '\0';
            std::cout << buff << std::endl;
        }
    }
    catch(const SocketException& se)
    {
        std::cout << se.What() << std::endl;
    }
}

The first time I connect to this everything is fine. If I close the client a SocketException occures (and therefore new hosting begins).

the host function:

    m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

m_address.sin_family = AF_INET;
m_address.sin_port = htons(port);
m_address.sin_addr.S_un.S_addr = INADDR_ANY;

int optval = 1;
setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof(int));

int retval = bind(m_socket, reinterpret_cast<sockaddr*>(&m_address), sizeof(m_address));

if(retval == SOCKET_ERROR)
    throw SocketException("bind() error", __FUNCTION__, WSAGetLastError());

retval = listen(m_socket, SOMAXCONN);

if(retval == SOCKET_ERROR)
    throw SocketException("listen() error", __FUNCTION__, WSAGetLastError());

m_socket = accept(m_socket, NULL, NULL);

if(m_socket == INVALID_SOCKET)
    throw SocketException("accept() error", __FUNCTION__, WSAGetLastError());

I need the setsockopt line becouse I'd like to bind instantly after an error (and the last hosting socket is in TIME_WAIT state?). Without setsockopt I've got bind() errors. So I use setsockopt and it let's me host on the port without problem. However when I start the client again, and try to connect to the host no error occures and I can send data again. However the program does not accept any incoming connections (it's still stuck at accept(m_socket, NULL, NULL); line waiting for incoming connection). I assume that the client can connect somehow to the old socket. Is that possible?

(note: If I add WSACleanup(); WSAStartup(MAKEWORD(2, 2), &m_wsaData); lines to the host function, then everything is working as intended. I have no idea why. WSACleanup();WSAStartup(MAKEWORD(2, 2), &m_wsaData); helps me out only in my example program I made to investigate this issue. In the original program that 2 lines is not working.)

1
Are you creating a socket on the client afresh (i.e. call socket) after the failure before issuing connect? You also need to make sure you are closing a socket with error (both on server and client).Maksim Skurydzin
I close the entire client program (client.exe) and start it again. It manages to connect also manages to send data. (But to the wrong socket if it's possible. And yes I close the socket in the client.exe aswell, no idea if it matters or not if I close it.)user1131015

1 Answers

1
votes

You're calling bind() and listen() for each connection. You should do bind() and listen() once when your server starts, and then call only accept() repeatedly.

Also to do it properly you should spawn a new thread for each accept() call, otherwise people will be able to DOS your server by just opening a connection to it and then not sending anything.