Valhalla Legends Forums Archive | C/C++ Programming | NON-Blocking

AuthorMessageTime
Final
Ive been playing around with some Non-Blocking Source I found so I can use it to run my little online game.
I added a couple of checks and stuff yet for some reason the socket system isint being handled correctly Ive looked over it yet I havent found anything that might cause it.

My only conclusion is something is messing up when a new user connects Because ive been running alot of debug checks. But if someone can take a gander at it That would at least help with some comments.


--Im Still Trying to Understand Non-Blocking Because I'm new---
--Data Sent is just text because the game client isint to capable for a packet system.
[code]
#include <cstdlib>
#include <iostream>
#include <windows.h>
#include <winsock2.h>
#include <string.h>
#include <time.h>
#include <fstream>
#include <sstream>
#include <mysql/mysql.h>
#include <exception>
#include <stdio.h>
using namespace std;
#include "resources.h"

#define PORT 1030
#define BUFFERSIZE 8192

typedef struct _MYSOCKET_INFORMATION {
CHAR Buffer[BUFFERSIZE];
char* username;
bool loggedin;
char* xaxis,* yaxis,* world;
WSABUF DataBuf;
SOCKET Socket;
DWORD SendBytes;
DWORD RecvBytes;
} SOCKET_INFORMATION, * LPSOCKET_INFORMATION;

BOOL CreateSocketInformation(SOCKET s);
void FreeSocketInformation(DWORD Index);

DWORD TotalSockets = 0;
LPSOCKET_INFORMATION SocketList[FD_SETSIZE];

string datanum[13][2]={{"1002","Login Checking"},
                    {"1003","New User"}, //New User//
                    {"1001","Chat"}, //Chat//
                    {"1004","Online Check"}, //Online Check//
                    {"1005","Userlsit Update"}, //Userlist Update//
                    {"1006","Wisper"}, //Wisper//-Under Construction
                    {"1007","Movement"}, //Movement//
                    {"1008","Update"}, //Update//
                    {"1009","Name Check"}, //Name Check//
                    {"1011","World Change"}, //World Change//
                    {"1013","Server Broadcast"}, //Server Broadcast//
                    {"1015","Server MOTD"},//Server MOTD//
                    {"1016","NPC Drop"}}; //NPC Set//
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(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];

        // 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;
              //printf("%s\n",SocketInfo->DataBuf.buf);
              string data =(string)SocketInfo->DataBuf.buf;
              string check = data.substr(0, 4);
              if(datanum[0][0].compare(check)==0 && SocketInfo->loggedin!=true){
              int loc = data.find( "@", 0 );                                 
              char user[MAX_PATH];
              char pass[MAX_PATH];
              string src=data.substr(4,loc-4);
              int ploc=data.find("@",loc-4);
              string psrc=data.substr(5+src.size(),data.size()-src.size()-6);
              sprintf(user,"%s",src.c_str());
              sprintf(pass,"%s",psrc.c_str());
              SocketInfo->username = user; 
              bool res=mysql_check(user,pass,SocketInfo->Socket);                         
              if(res==true){
              SocketInfo->loggedin=true;
              }
              }
             
             
              for (int b = 0; b < TotalSockets; b++){
              LPSOCKET_INFORMATION SocketInf = SocketList[b];
              if(SocketInfo->Socket!=SocketInf->Socket && SocketInfo->loggedin==true && SocketInf->loggedin!=false){
              send(SocketInf->Socket,SocketInfo->DataBuf.buf,SocketInfo->RecvBytes,0);
              printf("Recieved Data From %s\n",SocketInfo->username);
              }
              }
              // If zero bytes are received, this indicates connection is closed.
              if (RecvBytes == 0)
              {
                      FreeSocketInformation(i);
                      continue;
              }
        }
  }


// If the Writer is marked on this socket then this means the internal
// data buffers are available for more data.

    if (FD_ISSET(SocketInfo->Socket, &Writer))
    {
          Total--;

          SocketInfo->DataBuf.buf = SocketInfo->Buffer + SocketInfo->SendBytes;
          SocketInfo->DataBuf.len = SocketInfo->RecvBytes - SocketInfo->SendBytes;
          printf("%s\n",SocketInfo->username);
          DWORD SendBytes;
          if (WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0,
            NULL, NULL) == SOCKET_ERROR)
          {
                if (WSAGetLastError() != WSAEWOULDBLOCK)
                {
                    printf("Send failed with error\n");
                    FreeSocketInformation(i);
          }

          continue;
      }
      else
      {
          SocketInfo->SendBytes += SendBytes;

          if (SocketInfo->SendBytes == SocketInfo->RecvBytes)
          {
            SocketInfo->SendBytes = 0;
            SocketInfo->RecvBytes = 0;
          }
        }
      }
    }
  }
}

BOOL CreateSocketInformation(SOCKET s)
{
    LPSOCKET_INFORMATION SI;

    printf("Accepted socket\n");

    if ((SI = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR,
        sizeof(SOCKET_INFORMATION))) == NULL)
    {
        printf("Winsock tutorial error: GlobalAlloc() failed\n");
        return FALSE;
    }

// Prepare SocketInfo structure for use.

    SI->Socket = s;
    SI->SendBytes = 0;
    SI->RecvBytes = 0;
    SI->loggedin = false;
    SocketList[TotalSockets] = SI;
    TotalSockets++;

    return(TRUE);
}

void FreeSocketInformation(DWORD Index)
{
    LPSOCKET_INFORMATION SI = SocketList[Index];
    DWORD i;
    SI->loggedin=false;
    if(SI->username!=NULL){
    printf("%s:%d has Disconnected!\n",SI->username,Index);
    }
    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];
    }
         
    TotalSockets--;
}

[/code]
January 5, 2007, 8:19 AM
Kp
What happens when you run this?  What do you expect to happen?  Do you have any suspicions about particular lines being incorrect, or are you expecting us to check the entire posting for errors?
January 5, 2007, 2:46 PM
TheMinistered
Assuming you have a knowledge of how to utilize the C++ language and that you know how to use win32 apis.  You should consult msdn.microsoft.com, basically double check your code.  Also, you assuming you have some debugging skills... you should play around with it.

If you always come here to have us solve your problems, chances are you will never code a really complex game.  You'll have more than your share of problems, more than we could answer in an entire year ;}

So, my suggestion is toy with it and see what you can do.  If you solve this problem on your own, chances are you'll never run into the problem again or if you do, you'll know the right solution
January 5, 2007, 5:33 PM
Final
Ok well my problem is that the data isint stored correctly and this server isint gonna be very complex just for a basic little flash game.

Lets say the user logs in the data is stored in struct-
Another User Connects their data is stored on top of other users info-
When this happens server only holds onto two connections because data isint holding correctly thats my only problem at the moment.


Oh and I come every now and then for different problems I usually just figure them out myself now but I have tried to fix this for 2 days -in hours but no luck, debugging on my part came to the socket accept function yet I dont see anything wrong. But thats it really.
January 5, 2007, 11:06 PM
Kp
OK, that's better, but it's still not clear to me what is going wrong.  Please indicate specifically which data structures are not as you expect, and what is wrong with them.
January 6, 2007, 5:47 AM
Final
Ok Np

[code]
void FreeSocketInformation(DWORD Index)
{
    LPSOCKET_INFORMATION SI = SocketList[Index];
    DWORD i;
    SI->loggedin=false;
    if(SI->username!=NULL){
    printf("%s:%d has Disconnected!\n",SI->username,Index);
    }
    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];
    }
       
    TotalSockets--;
}
[/code]

That function goes ahead and accepts socket into struct

This is the Struct
[code]
typedef struct _MYSOCKET_INFORMATION {
CHAR Buffer[BUFFERSIZE];
char* username;
bool loggedin;
char* xaxis,* yaxis,* world;
WSABUF DataBuf;
SOCKET Socket;
DWORD SendBytes;
DWORD RecvBytes;
} SOCKET_INFORMATION, * LPSOCKET_INFORMATION;

[/code]

Then it goes ahead and ads it to the struct array.

[code]
LPSOCKET_INFORMATION SocketList[FD_SETSIZE];
[/code]

Yet when a new user connects it just rewrites over the one before it so it dont work right.

Yet I have seen nothing wrong I understand where it pinpointed but i dont understand its probably something so minuscule i dont even see it lol.

I could be wrong though it might be something else but Im sure its their.




January 6, 2007, 1:16 PM
Kp
A quick survey shows nothing obviously wrong with the code.  If you are comfortable using a debugger, step through the code which handles accepting a new client.  Otherwise, add the enclosed function and add calls to it which bracket the area which you suspect is causing trouble.  Move the calls closer together until you find the line which fails.

[code]
void PrintSockets()
{
printf("Total entries=%u\n", TotalSockets);
for (DWORD i = 0; i < TotalSockets; ++i)
printf("\t%u: %p \"%s\"\n", i, SocketList[i], SocketList[i]->username);
printf("\n");
}[/code]

This will print how many users you have, and for each index that you consider valid, it will print that index, the address of the data structure, and the name (if any) of the user in that data structure.  You can use this to see which user(s) are erased, whether entries are duplicated, etc.
January 6, 2007, 7:14 PM
Final
Oh Ive done this after this on practically the whole code were anything is handled like output the users info when they join and shit but yah but Ill go ahead and try it because Im looking for any help I can get. Thanks KP
January 6, 2007, 10:43 PM

Search