У меня есть программа, и она прослушивает порт 200. После того, как к нему подключен клиент, все полученные от клиента данные записываются в std :: cout. Если при получении данных от клиента произойдет какая-либо ошибка, я бы хотел перезапустить хостинг.
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;
}
}
Первый раз подключаюсь к этому все нормально. Если я закрываю клиент, возникает SocketException (и, следовательно, начинается новый хостинг).
функция хоста:
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());
Мне нужна строка setsockopt, потому что я хотел бы связать сразу после ошибки (и последний хост-сокет находится в состоянии TIME_WAIT?). Без setsockopt у меня есть ошибки bind ().
Поэтому я использую setsockopt, и он позволяет мне без проблем размещать порт. Однако, когда я снова запускаю клиент и пытаюсь подключиться к хосту ошибок нет и я могу отправить данные еще раз.
Однако программа не принимает входящие соединения (он все еще застрял при принятии (m_socket, NULL, NULL); линия ожидает входящего соединения). Я предполагаю, что клиент может как-то подключиться к старому сокету. Это возможно?
(нота:
Если я добавлю WSACleanup ();
WSAStartup (MAKEWORD (2, 2), &m_wsaData);
линии к функции хоста, затем все работает как предполагалось. Понятия не имею почему.
WSACleanup (); WSAStartup (MAKEWORD (2, 2), &m_wsaData); выручает меня только в моем примере программы, которую я сделал, чтобы исследовать эту проблему. В оригинальной программе эта 2 строки не работает.)
Ты звонишь bind()
а также listen()
для каждого соединения. Ты должен сделать bind()
а также listen()
один раз, когда ваш сервер запускается, а затем позвонить только accept()
несколько раз.
Также, чтобы сделать это правильно, вы должны создать новую ветку для каждого accept()
позвоните, в противном случае люди смогут DOS вашего сервера, просто открыв соединение с ним, а затем ничего не отправляя.
Других решений пока нет …