Non-Blocking Server help.
Hello everyone, havent been here in a long time it seems php got the better of me lol.
Well I've been working on a server for a while and stuff and have a struct that contains userinformation but when A user connects they get new data and such :D so username is good to go in .
My problem is when I try disconnecting I want to display who is the user that is doing that So i display it.. Bam first one works great right name and everything..
For the 2nd one not so good it keeps the name from the first one Could someone tell me what might be the case here is my code really stripped down.
The Struct im having problems with is the _USER_DATA struct.
Code:
#define PORT 1030
#define BUFFERSIZE 8192
typedef struct _MYSOCKET_INFORMATION {
CHAR Buffer[BUFFERSIZE];
WSABUF DataBuf;
SOCKET Socket;
DWORD SendBytes;
DWORD RecvBytes;
} SOCKET_INFORMATION, * LPSOCKET_INFORMATION;
typedef struct _USER_DATA{
char* username;
bool online;
}US_INFORMATION, * USER_INFORMATION;
BOOL CreateSocketInformation(SOCKET s);
void FreeSocketInformation(DWORD Index);
DWORD TotalSockets = 0;
LPSOCKET_INFORMATION SocketList[FD_SETSIZE];
USER_INFORMATION UserList[FD_SETSIZE];
int main()
{
SOCKET ListenSocket;
SOCKET AcceptSocket;
SOCKADDR_IN InternetAddr;
WSADATA wsaData;
FD_SET Writer;
FD_SET Reader;
ULONG NonBlock;
DWORD Flags;
int Ret;
if ((Ret = WSAStartup(MAKEWORD(2,0),&wsaData)) != 0)
{
//startup failed
}
// Create a socket for the winsock tutorial.
if ((ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,
WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("Winsock tutorial error: WSASocket() failed %d\n", WSAGetLastError());
return 0;
}
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InternetAddr.sin_port = htons(atoi(port));
if (bind(ListenSocket, (SOCKADDR *) &InternetAddr, sizeof(InternetAddr))== SOCKET_ERROR)
{
printf("Winsock tutorial error: Binding failed %d\n", WSAGetLastError());
return 0;
}
if (listen(ListenSocket, 5))
{
printf("Winsock tutorial error: listen failed %d\n", WSAGetLastError());
return 0;
}
// Change the socket mode on the listening socket from blocking to non-block
NonBlock = 1;
if (ioctlsocket(ListenSocket, FIONBIO, &NonBlock) == SOCKET_ERROR)
{
printf("ioctlsocket() failed \n");
return 0;
}
while(TRUE)
{
// Initialize the Read and Write socket set.
FD_ZERO(&Reader);
FD_ZERO(&Writer);
// Check for connection attempts.
FD_SET(ListenSocket, &Reader);
// Set Read and Write notification for each socket based on the
// current state the buffer.
int Total;
for (int i = 0; i < TotalSockets; i++)
if (SocketList[i]->RecvBytes > SocketList[i]->SendBytes)
FD_SET(SocketList[i]->Socket, &Writer);
else
FD_SET(SocketList[i]->Socket, &Reader);
if (( Total = select(0, &Reader, &Writer, NULL, NULL)) == SOCKET_ERROR)
{
printf("Winsock tutorial error: select function returned with error %d\n", WSAGetLastError());
return 0;
}
// Check for arriving connections on the listening socket.
if (FD_ISSET(ListenSocket, &Reader))
{
Total--;
if ((AcceptSocket = accept(ListenSocket, NULL, NULL)) != INVALID_SOCKET)
{
// Set the accepted socket to non-blocking mode so the server will
// not get caught in a blocked condition on WSASends
NonBlock = 1;
if (ioctlsocket(AcceptSocket, FIONBIO, &NonBlock) == SOCKET_ERROR)
{
printf("Winsock tutorial error: ioctlsocket() failed with error %d\n", WSAGetLastError());
return 0;
}
if (CreateSocketInformation(AcceptSocket) == FALSE)
return 0;
}
else
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
printf("accept() failed with error %d\n", WSAGetLastError());
return 0;
}
}
}
// Check each socket for Read and Write notification for Total number of sockets
for (int i = 0; Total > 0 && i < TotalSockets; i++)
{
LPSOCKET_INFORMATION SocketInfo = SocketList[i];
USER_INFORMATION UserInfo = UserList[i];
// If the Reader is marked for this socket then this means data
// is available to be read on the socket.
if (FD_ISSET(SocketInfo->Socket, &Reader))
{
Total--;
SocketInfo->DataBuf.buf = SocketInfo->Buffer;
SocketInfo->DataBuf.len = BUFFERSIZE;
Flags = 0;
DWORD RecvBytes;
if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes,
&Flags, NULL, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
printf("Winsock tutorial: Receive failed with error\n");
FreeSocketInformation(i);
}
continue;
}
else
{
SocketInfo->RecvBytes = RecvBytes;
//user== username given dynamically//
if(res==true)UserInfo->online=true;UserInfo->username=user;
}
// If zero bytes are received, this indicates connection is closed.
if (RecvBytes == 0)
{
FreeSocketInformation(i);
continue;
}
}
}
}
}
}
BOOL CreateSocketInformation(SOCKET s)
{
LPSOCKET_INFORMATION SI;
USER_INFORMATION INFO;
printf("Accepted socket\n");
if ((SI = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR,
sizeof(SOCKET_INFORMATION))) == NULL)
{
printf("Winsock tutorial error: GlobalAlloc() failed\n");
return FALSE;
}
if((INFO = (USER_INFORMATION) GlobalAlloc(GPTR,sizeof(US_INFORMATION))) == NULL)printf("ERROR");
// Prepare SocketInfo structure for use.
SI->Socket = s;
SI->SendBytes = 0;
SI->RecvBytes = 0;
UserList[TotalSockets] = INFO;
SocketList[TotalSockets] = SI;
TotalSockets++;
return(TRUE);
}
void FreeSocketInformation(DWORD Index)
{
LPSOCKET_INFORMATION SI = SocketList[Index];
USER_INFORMATION INFO = UserList[Index];
DWORD i;
//HERE IS WERE IT OUTPUTS ON DISCONNECT//
if(INFO->username!=NULL){
printf("%s has Disconnected!\n",INFO->username);
}
closesocket(SI->Socket);
printf("Closing socket\n");
GlobalFree(SI);
// Remove from the socket array
for (i = Index; i < TotalSockets; i++)
{
SocketList[i] = SocketList[i + 1];
UserList[i] = UserList[i + 1];
}
TotalSockets--;
}