Advertisement

Please Help w/ Winsock Logic!!!

Started by September 29, 2002 05:59 PM
9 comments, last by DycewareInd 22 years, 4 months ago
I have doggedly referenced back to the resources section on this site to figure out how to make an async server. Richard Hallett's article is exactly what I need: an async socket server for console. (!Windows). As much as I try to change things, I have a consistant problem. It would seem that select(...); always thinks there is a client wanting to connect. Here's my code:
  
CCybServer g_Server[10];


int main()    
{  

int i=0;


int nfds=0; //compatibility (dunno)

fd_set conn; //setup read variable for select  

int stored=0; //where data stored 

int Clients=1; //clients connected (i mean that to be a 1)


//Make all my mini-servers

 while(i<10)
 {
  g_Server[i].Init();
  g_Server[i].CreateSocket(5000);
  g_Server[i].Listen();
  g_Server[i].m_iID=i;
  i++;
 }
  
while(1) 
{ 
 
   i=0;
    
   while(i<Clients)
   {  
   stored=0; //i have to reset this to 0 because this isn't in

             //a seperate function at the moment


//All this for select...


g_Server[i].timeout.tv_sec=0;   //what makes it non-blocking

g_Server[i].timeout.tv_usec=0;  //


FD_ZERO(&conn); //set conn to nothing 


FD_SET(g_Server[i].m_CybSocket, &conn); //if i !do this, no one

                                        //connects


//get data from server/listening socket


nfds=g_Server[i].m_CybSocket+1; //compatibility (?)

 
 
stored = select(nfds, &conn, NULL, NULL, &g_Server[i].timeout);
 //anything trying to get in?

 

//If it's a logic error on my part: 

//here's where it would  occur...


 if(stored>0) //meaning select got something

 {
  
if(g_Server[i].m_bUsed==false) //m_bUsed means it's been connect

{ 
 Clients++;
 g_Server[i].Accept(); //standard accept code    

 g_Server[i].m_bUsed=true; //therefore that "server" in use

}
    
}   
 
//Standard send and receive, just bouncing info 

//back in this case...

               
   g_Server[i].Receive();
   g_Server[i].Send(g_Server[i].m_szReceive);  
   i++;
   }
   
 }
}
  
I realize it's rough, but if you can decipher my abhorent tabbing and give me a hint I'd appreciate it. It'd be preferable not to change code as much as possible (I know that's terrible server design, but I have matchingly terrible client design and that'd prolly just lead to more questions that i could figure out for myself otherwise Thanks again. [edited by - DycewareInd on October 4, 2002 5:41:05 PM] [edited by - DycewareInd on October 5, 2002 12:04:50 PM]
D''ware
It seems that after checking if you got anything on the socket (with a timeout of 0) you then go ahead and do receive and send on it regardless. Maybe you pasted something a bit wrong here, because I''m pretty sure
while(i {
would not compile

Are you binding all 10 sockets to port 5000?

From linux man pages: "On success, select returns the number of descriptors contained in the descriptor sets" You need to use FD_ISSET() after select to see if the descriptor that you are interested in is actually set...
Advertisement
quote:
Original post by zppz
Maybe you pasted something a bit wrong here, because I''m pretty sure
while(i {
would not compile



Actually, there''s probably a < after the i which is being interpreted as a "start of HTML tag"...

DycewareInd, edit your post and change all instances of < with "&lt;"

If I had my way, I''d have all of you shot!


codeka.com - Just click it.

oh yeah. Or just put
    
tags around it
bugger
i would say that there''s everything correct around the function select. But i dont know what nfds is. I normally set this parameter to FD_SETSIZE. But i dont understand it, i have seen it in a book.

perhaps you really have always a client who wants to connect. I mean it is really difficult to say with that code. perhaps you should also show the class ccybserver.

The problem of Object Oriented Programming:Everybody tells you how to use his classes, but nobody how not to do it !
Advertisement

  class CCybServer{ public:  SOCKET m_CybSocket;   //listening socket  SOCKET m_ClientSocket; //client socket   SOCKADDR_IN m_SockIn;    //address of serve  SOCKADDR_IN m_SockAccept; //client address  WSADATA m_WSAData;  //for init  int m_iMaxPendingConnects; //how many to que  int m_iAcceptLength;   int m_iReceive;  int m_iIndex;  bool m_bUsed;  int m_iClients;  int m_iID;  timeval timeout; //how long to wait  char m_szReceive[100];  TCHAR m_szReceiveString[100];  int CreateSocket(int iPortNumber);  int Listen();  int Accept();  int Receive();  int Convert();  int ShutDown();  int CloseSocket();  int Send(char *szSendString);  int Init();  int CleanUp();};class CCybClient{ public:  SOCKET m_ServerSocket;  SOCKADDR_IN m_SockIn;  PHOSTENT m_phostent;  WSADATA m_WSAData;  int m_iAcceptLength;  int m_iReceive;   int m_iIndex;    bool m_bUsed;  char m_szReceive[100];  TCHAR m_szReceiveString[100];  int CreateSocket();  int GetHost(char *szHostName, int iPortNumber);  int Connect();  int Receive();  int Send(char *szSendString);  int Init();  int CleanUp();  int ShutDown();  int CloseSocket();};int CCybServer::Init(){  if (WSAStartup (MAKEWORD(1,1),&m_WSAData) != 0)  {    cout<<"Failed Startup";    return FALSE;  }  m_bUsed=false;  m_iClients=0;  return 0;}int CCybClient::Init(){  if (WSAStartup (MAKEWORD(1,1),&m_WSAData) != 0)  {    cout<<"Failed Startup";    return FALSE;  }    m_bUsed=false;  return 0;}//Open up sockeint CCybServer::CreateSocket(int iPortNumber){//Identical (almost) to tutorial    m_SockIn.sin_family = AF_INET;    m_SockIn.sin_port = htons (iPortNumber);  m_SockIn.sin_addr.s_addr = htonl (INADDR_ANY);//Create the socket (listening) if ((m_CybSocket = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)  {    cout<<"Failed Create";    return FALSE;  }  //bind newly created socket  if (bind (m_CybSocket,(struct sockaddr *) &m_SockIn,      sizeof (m_SockIn)) == SOCKET_ERROR)  {    //cout<<"Failed bind";    closesocket (m_CybSocket);    return FALSE;  }  return 0;}//Anyone there?int CCybServer::Listen(){ if(listen (m_CybSocket, m_iMaxPendingConnects) == SOCKET_ERROR)  {    //cout<<"Failed listen";    closesocket (m_CybSocket);    return FALSE;  }  m_iAcceptLength = sizeof (m_SockAccept);    /*TUTORIAL: MAKE ALL CLIENTS=NOT IN USE?*/  return 0;}//THIS IS WHAT IS RADICALLY DIFF FROM TUTORIAL!!! int CCybServer::Accept(){//if(stored>0) //someone wants in//{ //cout<<endl<<"ACCEPTED";if(m_CybSocket!=0){m_ClientSocket = accept (m_CybSocket,    (struct sockaddr *) &m_SockAccept,    (int *) &m_iAcceptLength);    cout<<endl<<"ACCEPTED";    m_bUsed=true;}//}                        //closesocket(m_CybSocket); return 1;}int CCybServer::Receive(){    m_iReceive = recv (m_ClientSocket, m_szReceive, sizeof (m_szReceive), 0);    if (m_iReceive == SOCKET_ERROR)    {      //cout<<"Failed receive";      return FALSE;    }    else    {      for (m_iIndex = 0; m_iIndex <= sizeof (m_szReceive); m_iIndex++)        m_szReceiveString[m_iIndex] = m_szReceive[m_iIndex];    }  return 0;}int CCybServer::Send(char *szSendString){ if (send (m_ClientSocket, szSendString, strlen (szSendString) + 1, 0)           == SOCKET_ERROR)   {  //cout<<"Failed send";   return FALSE;  }  return 0;}int CCybServer::ShutDown() {  shutdown (m_ClientSocket, 0x02);  return 0; } int CCybServer::CloseSocket() {  closesocket (m_ClientSocket);  return 0; }int CCybServer::CleanUp(){ WSACleanup (); return 0;}int CCybClient::ShutDown() {  shutdown (m_ServerSocket, 0x00);  return 0; } int CCybClient::CloseSocket() {  closesocket (m_ServerSocket);  return 0; } int CCybClient::CleanUp(){ WSACleanup (); return 0;}int CCybClient::CreateSocket(){ if ((m_ServerSocket = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)  {    return FALSE;  }  m_SockIn.sin_family = AF_INET;  return 0;}int CCybClient::GetHost(char *szHostName, int iPortNumber){ // Retrieve the host information corresponding to the host name.  if ((m_phostent = gethostbyname (szHostName)) == NULL)  {    closesocket (m_ServerSocket);    return FALSE;  }  // Assign the socket IP address.  memcpy ((char FAR *)&(m_SockIn.sin_addr),          m_phostent->h_addr,          m_phostent->h_length);  // Convert to network ordering.  m_SockIn.sin_port = htons (iPortNumber);  return 0;}int CCybClient::Connect(){ if (connect (m_ServerSocket,               (PSOCKADDR) &m_SockIn,               sizeof (m_SockIn)) == SOCKET_ERROR)  {    closesocket (m_ServerSocket);    return FALSE;  }  return 0;}int CCybClient::Send(char *szSendString){ if (send (m_ServerSocket, szSendString, strlen (szSendString) + 1, 0)           == SOCKET_ERROR)   {  //cout<<"BANG BANG";   return FALSE;  }  return 0;}int CCybClient::Receive(){    //cout<<"Receiving.";    m_iReceive = recv (m_ServerSocket, m_szReceive, sizeof (m_szReceive), 0);    if (m_iReceive == SOCKET_ERROR)    {      cout<<"Failed receive";      return FALSE;    }    else    {      for (m_iIndex = 0; m_iIndex <= sizeof (m_szReceive); m_iIndex++)        m_szReceiveString[m_iIndex] = m_szReceive[m_iIndex];    }  return 0;}  


Someone please tell me how to put that in a code box?

That's what I've got for my CybServer/Client classes

Why can't I bind them all to 5000?

[edited by - DycewareInd on October 4, 2002 5:53:36 PM]

[edited by - DycewareInd on October 5, 2002 12:05:23 PM]
D''ware
Put it inside [ source ] and [ /source ] (without the spaces)

You can''t bind them all to the same port because that doesn''t make sense. If you''ve got 10 programs all listening on the same port and something comes in, which program does it go to?

If I had my way, I''d have all of you shot!


codeka.com - Just click it.

just a few more thoughts:

u call WSAStartup ten times
u bind to same port ten times, error msg is commented out //cout<<"Failed bind";
this means listen would fail? error msg is commented out //cout<<"Failed listen";
u call Receive() whether or not select got something, i guess it would fail, error msg is commented out //cout<<"Failed receive";

What output do you get with error msgs UNcommented??
Ok... I see what u''re saying about multiple ports. I didn''t understand that. In fact that''ll solve the problem I think. But how can I tell my clients which port is already binded?
D''ware

This topic is closed to new replies.

Advertisement