Консультация № 160210
11.02.2009, 17:11
0.00 руб.
0 4 0
Уважаемые эксперты!
В приложении код сервера, который должен "висеть" и слушать порт. К нему коннектятся клиенты. Но в самом сервере имеется какой-то баг. Два (могут успеть три или четыре) клиента коннектятся и после этого порт оказывается в дауне, хотя те кто успел вполне нормально работают. Помогите найти ошибку. Баг 100% на стороне сервера, т.к. коннект разными клиентами (включая telnet) даёт одинаковый эффект. Написанный же на дельфи аналогичный сервер работает без вопросов, хоть с 20-тью клиентами.

Приложение:
typedef unsigned (__stdcall *PTHREAD_START) (void *);

int main() {
WSADATA wsaData;
WORD wVerRequested = MAKEWORD( 2, 2 );
WSAStartup(wVerRequested, &wsaData);

SOCKET m_Socket;
SOCKADDR_IN sin;
int nRes;

while (1) {
m_Socket = socket (PF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET != m_Socket) {
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = 0;
sin.sin_port = htons(500);

nRes = bind (m_Socket, (PSOCKADDR) &sin, sizeof (sin));
if (SOCKET_ERROR != nRes) {
nRes = listen (m_Socket, 1);
if (SOCKET_ERROR != nRes) {
SOCKADDR_IN sin;
int iSize = sizeof(sin);
SOCKET ListenSocket = m_Socket;
m_Socket = accept(ListenSocket, (PSOCKADDR)&sin, &iSize);
if (INVALID_SOCKET != m_Socket) {
closesocket(ListenSocket);
send(m_Socket, "Hello from server", _tcslen("Hello from server"), 0);

DWORD dwThreadId;
HANDLE hThread = (HANDLE)_beginthreadex((void*)NULL, 0,
(PTHREAD_START)UserProc, (PVOID)m_Socket, 0, (unsigned*)&dwThreadId);
}
}
}
}

int iErr = WSAGetLastError();
if (iErr)
break;
}

return (S_OK);
}

DWORD WINAPI UserProc(LPVOID lpvoid) {
SOCKET m_Socket = (SOCKET)lpvoid;

int cbRead = 50;
TCHAR szData[50];
recv(m_Socket, szData, cbRead, 0);

return (S_OK);
}

Обсуждение

Неизвестный
11.02.2009, 20:04
общий
Попробуйте вынести создание сокета и привязку его к порту из цикла, а в цикле оставить только listen и accept. Может быть после этого проблема решится.
давно
Академик
20764
1861
11.02.2009, 21:50
общий
В linux такое работать вообще не должно: после закрытия слушающего сокета порт освобождается далеко не сразу (через несколько минут) и уже второй bind() должен не удасться. Там с этим можно бороться, установив с помощью setsockopt() опцию SO_REUSE.
Но в вашем случае каждый раз его переоткрывать действительно странное решение.
Неизвестный
12.02.2009, 06:46
общий
Спасибо огромное за советы. Это не мой код. Я в сях не силён. И с сокетами познакомился пару дней назад. Но чувствую спинным мозгом что вы абсолютно правы. Хвала вам и почёт! Куда заэсэмэсить для благодарностей?
Неизвестный
12.02.2009, 14:31
общий
Уважаемые эксперты! Всё было именно так, как вы и сказали. Теперь всё работает без вопросов. Спасибо огромное за помощь.
Форма ответа