Are you sure that the client application has terminated? Maybe your thread
AliR.
I am writing a program for chating with another user in LAN. This
program uses UDP to send messages.
When I sent a message to another peer who has already closed his
program, the last message of the peer will be sent to me. I am sure
the message is sent by peer's computer. (Because unplug peer's line
will stop this problem and will reproduce this problem after re-plug
peer's line.)
Can anyone tell me why this problem occurs and how to prevent this
message to be sent?
----------------------------------
Here is my code to start a socket (At begin of program):
CChating::CChating() : m_socket(NULL), m_pooling(NULL), m_stop(false),
m_buf(NULL), m_wnd(NULL), m_lenbuf(0)
{
DECLARE_EXCEPTION_SCOPE(CChating::CChating, true)
WSADATA wd={0};
int i=0;
i=WSAStartup(MAKEWORD(2, 2), &wd);
ON_FAIL(i==0,
MMSG("Winsock can not be initialized. (%d)", i),
CChating_CChating_Fail);
m_socket=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
ON_WSA_FAIL(m_socket!=INVALID_SOCKET,
socket, "Fail to create socket.",
CChating_CChating_Fail);
i=-1;
ON_WSA_FAIL(setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, (char
*)&i, sizeof(int))!=SOCKET_ERROR,
setsockopt, "Fail to enable broadcasting.",
CChating_CChating_Fail);
i=sizeof(m_lenbuf);
ON_WSA_FAIL(getsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char
*)&m_lenbuf, &i)!=SOCKET_ERROR,
ioctlsocket, "Fail to determine max buffer size.",
CChating_CChating_Fail);
m_stop=false;
m_pooling=CreateThread(NULL, 0, pooling_func, this, 0, NULL);
ON_WIN32_FAIL(m_pooling,
CreateThread, "Fail to start pooling.",
CChating_CChating_Fail);
ON_FAIL(WaitForSingleObject(m_pooling, 1000)==WAIT_TIMEOUT,
"The pooling thread has abnormally terminated.",
CChating_CChating_Fail);
m_buf=(PBYTE)malloc(m_lenbuf);
ON_CRT_FAIL(m_buf,
malloc, "Fail to alloc receving buffer.",
CChating_CChating_Fail);
CoCreateGuid((GUID *)m_buf);
gethostname((char *)&m_buf[sizeof(GUID)], 256);
m_me=peer_t(*(GUID *)m_buf, M2W((char *)&m_buf[sizeof(GUID)]),
L"0.0.0.0");
return;
CChating_CChating_Fail:
closesocket(m_socket);
WSACleanup();
EXCEPTION_HANDLER_END()
}
----------------------------------
Here is my code to end a socket (At end of program):
CChating::~CChating()
{
DECLARE_DBG_SCOPE(CChating::~CChating, true)
DWORD i=0;
DBG(_T("Pre-exit.\n"));
m_stop=true;
if(WaitForSingleObject(m_pooling, 2000)==WAIT_TIMEOUT)
TerminateThread(m_pooling, -1);
DBG(_T("Post-exit.\n"));
free(m_buf);
shutdown(m_socket, SD_BOTH);
closesocket(m_socket);
WSACleanup();
}
----------------------------------
Here is my code to wait messages (At a pooling thread):
DWORD __stdcall CChating::pooling_func(LPVOID data)
{
DECLARE_EXCEPTION_SCOPE(CChating::pooling_func, true)
CChating *me=(CChating *)data;
SOCKET socket=me->m_socket;
bool &stop=me->m_stop;
PBYTE &buf=me->m_buf;
HWND &wnd=me->m_wnd;
int &lenbuf=me->m_lenbuf;
peer_t &_me=me->m_me;
DWORD i=0, j;
packet_t *packet=NULL;
fd_set fs={0};
timeval tv={1, 0};
sockaddr_in sa={0};
me->init_sockaddr_in(sa, htonl(0));
ON_WSA_FAIL(bind(socket, (sockaddr *)&sa, sizeof(sockaddr_in))!
=SOCKET_ERROR,
bind, "Fail to bind address.",
CChating_pooling_func_Fail);
while(!stop)
{
FD_ZERO(&fs);
FD_SET(socket, &fs);
i=(DWORD)select(0, &fs, NULL, NULL, &tv);
DBG(L"The result of select: %x\n", i);
ON_WSA_FAIL((int)i!=SOCKET_ERROR,
select, "Fail to determine the status of socket.",
CChating_pooling_func_Fail);
if(!stop && (int)i)
{
*(int *)&i=sizeof(sa);
j=recvfrom(socket, (char *)buf, lenbuf, 0, (sockaddr *)&sa, (int
*)&i);
packet=(packet_t *)buf;
wcscpy(packet->m_peer.m_addr, M2W(inet_ntoa(sa.sin_addr)));
switch(packet->m_mark)
{
case GETPEER_MARK:
if(!(_me==packet->m_peer))
{
DBG(_T("GETPEER_MARK, %s, %s\n"), packet->m_peer.m_name, packet-
m_peer.m_addr);
if((bool)SendMessage(wnd, WM_GOTPEER, 0, (LPARAM)&packet->m_id))
me->peer_op(sa.sin_addr.S_un.S_addr, packet->m_mark-1, packet-
m_id);
}
break;
case GETPEER_MARK-1:
DBG(_T("[ACK] GETPEER_MARK, %s, %s\n"), packet->m_peer.m_name,
packet->m_peer.m_addr);
SendMessage(wnd, WM_GOTPEER, 0, (LPARAM)&packet->m_id);
break;
case REMOVE_MARK:
DBG(_T("REMOVE_MARK, %s, %s\n"), packet->m_peer.m_name, packet-
m_peer.m_addr);
SendMessage(wnd, WM_RMPEER, 0, (LPARAM)&packet->m_id);
break;
case INVITE_MARK:
DBG(_T("INVITE_MARK, %s, %s\n"), packet->m_peer.m_name, packet-
m_peer.m_addr);
if((bool)SendMessage(wnd, WM_INVITED, 0, (LPARAM)&packet->m_id))
me->peer_op(htonl(-1), GETPEER_MARK, packet->m_id);
break;
default:
DBG(_T("MESSAGE, %s, %s, %s\n"), packet->m_peer.m_name, packet-
m_peer.m_addr, packet->m_msg);
SendMessage(wnd, WM_GOTMSG, 0, (LPARAM)&packet->m_id);
}
}
}
me->peer_op(htonl(-1), REMOVE_MARK, GUID_NULL);
DBG(_T("Pooling thread is exiting.\n"));
EXCEPTION_HANDLER_BEGIN(CChating_pooling_func_Fail, 0)
DBG(_T("Pooling thread will not continue due to the following
problems.\n"));
DBG(_T("%s\n"), M2T((char const *)*___e));
delete ___e;
return -1;
}