/
Inicio :: Foros

 F.A.Q.F.A.Q.                  Conéctese para revisar sus mensajesConéctese para revisar sus mensajes   

Problema con sockets tcp

 
      Índice del Foro elrincondelc.com -> Programación en Servidores
Ver tema anterior :: Ver siguiente tema  
AutorMensaje
Lanius



Registrado: 10 Oct 2007
Mensajes: 3

MensajePublicado: 20/09/2010 7:10 am
Título: Problema con sockets tcp

Saludos
Utilizo como compilador Dev-C++, bajo el sistema operativo Windows y estoy usando las librerías de SDL el problema es que estoy tratando de aprender el uso de sockets con SDL el siguiente ejemplo que subiré lo baje desde la página oficial de SDL_NET el cual bajo Linux funciona la perfección, y no he logrado hacerlo funcionar bajo Windows…. Espero su ayuda gracias.

tcpmulticlientthreaded.c
Código:
#include <string.h>
#ifndef WIN32
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#else
#include <windows.h>
#include <time.h>
#endif
#include <stdlib.h>
#include <SDL/SDL.h>
#include <SDL/SDL_thread.h>
#include <SDL/SDL_net.h>
#include "tcputil.h"

#define MAXLEN (1*10*1024) /* 10 KB - adequate for text */

int net_thread_main(void *);
int local_thread_main(void *);

int done=0;
SDL_Thread *net_thread=NULL, *local_thread=NULL;

int main(int argc, char **argv)
{
   IPaddress ip;
   TCPsocket sock;
   Uint16 port;
   char *name;

   /* check our commandline */
   if(argc<4)
   {
      printf("%s host port username\n",argv[0]);
      exit(0);
   }
   
   name=argv[3];
   
   /* initialize SDL */
   if(SDL_Init(0)==-1)
   {
      printf("SDL_Init: %s\n",SDL_GetError());
      exit(1);
   }

   /* initialize SDL_net */
   if(SDLNet_Init()==-1)
   {
      printf("SDLNet_Init: %s\n",SDLNet_GetError());
      SDL_Quit();
      exit(3);
   }

   /* get the port from the commandline */
   port=(Uint16) strtol(argv[2],NULL,0);
   
   /* Resolve the argument into an IPaddress type */
   printf("Connecting to %s port %d\n",argv[1],port);
   if(SDLNet_ResolveHost(&ip,argv[1],port)==-1)
   {
      printf("SDLNet_ResolveHost: %s\n",SDLNet_GetError());
      SDLNet_Quit();
      SDL_Quit();
      exit(5);
   }

   /* open the server socket */
   sock=SDLNet_TCP_Open(&ip);
   if(!sock)
   {
      printf("SDLNet_TCP_Open: %s\n",SDLNet_GetError());
      SDLNet_Quit();
      SDL_Quit();
      exit(6);
   }
   
   /* login with a name */
   if(!putMsg(sock,name))
   {
      SDLNet_TCP_Close(sock);
      SDLNet_Quit();
      SDL_Quit();
      exit(7);
   }

   printf("Logged in as %s\n",name);

   local_thread=SDL_CreateThread(local_thread_main,sock);
   if(!local_thread)
   {
      printf("SDL_CreateThread: %s\n",SDL_GetError());
      SDLNet_Quit();
      SDL_Quit();
      exit(8);
   }
   
   net_thread=SDL_CreateThread(net_thread_main,sock);
   if(!net_thread)
   {
      printf("SDL_CreateThread: %s\n",SDL_GetError());
      SDLNet_Quit();
      SDL_Quit();
      exit(9);
   }
   
   /* threads are doing the work now */
   /* we wait for them to finish on their own... */
   SDL_WaitThread(local_thread,NULL);
   SDL_WaitThread(net_thread,NULL);

   /* this shows our unique reason where the threads ended */
   printf("Finished code %d\n",done);
   
   /* shutdown SDL_net */
   SDLNet_Quit();

   /* shutdown SDL */
   SDL_Quit();

   return(0);
}

int local_thread_main(void *data)
{
   TCPsocket sock=(TCPsocket)data;
#ifndef _MSC_VER
   fd_set fdset;
   int result;
#endif
   char message[MAXLEN];

   while(!net_thread && !done)
      SDL_Delay(1);
   
   /* this is the local input loop */
   while(!done)
   {
#ifndef _MSC_VER
      /* set up the file descriptor set */
      FD_ZERO(&fdset);
      FD_SET(fileno(stdin),&fdset);
      
      /* wait for keyboard input on stdin */
      result=select(fileno(stdin)+1, &fdset, NULL, NULL, NULL);
      if(result==-1)
      {
         perror("select");
         done=6;
         break;
      }

      /* is there input? */
      if(result && FD_ISSET(fileno(stdin),&fdset))
      {
#endif
         /* get the string from stdin */
         if(!fgets(message,MAXLEN,stdin))
         {
            done=7;
            break;
         }

         /* strip the whitespace from the end of the line */
         while(strlen(message) && strchr("\n\r\t ",message[strlen(message)-1]))
            message[strlen(message)-1]='\0';

         /* if there was a message after stripping the end,  */
         /* send it to the server */
         if(strlen(message))
         {
            /*printf("Sending: %s\n",message); */
            putMsg(sock,message);
         }
#ifndef _MSC_VER
      }
#endif
   }
   if(!done)
      done=1;
   SDL_KillThread(net_thread);
   return(0);
}

/* the network input loop */
int net_thread_main(void *data)
{
   TCPsocket sock=(TCPsocket)data;
   SDLNet_SocketSet set;
   int numready;
   char *str=NULL;

   set=SDLNet_AllocSocketSet(1);
   if(!done && !set)
   {
      printf("SDLNet_AllocSocketSet: %s\n", SDLNet_GetError());
      SDLNet_Quit();
      SDL_Quit();
      done=2;
   }

   if(!done && SDLNet_TCP_AddSocket(set,sock)==-1)
   {
      printf("SDLNet_TCP_AddSocket: %s\n",SDLNet_GetError());
      SDLNet_Quit();
      SDL_Quit();
      done=3;
   }
   
   while(!done)
   {
      numready=SDLNet_CheckSockets(set, (Uint32)-1);
      if(numready==-1)
      {
         printf("SDLNet_CheckSockets: %s\n",SDLNet_GetError());
         done=4;
         break;
      }

      /* check to see if the server sent us data */
      if(numready && SDLNet_SocketReady(sock))
      {
         /* getMsg is in tcputil.h, it gets a string from the socket */
         /* with a bunch of error handling */
         if(!getMsg(sock,&str))
         {
            char *errstr=SDLNet_GetError();
            printf("getMsg: %s\n",strlen(errstr)?errstr:"Server disconnected");
            done=5;
            break;
         }
         /* post it to the screen */
         printf("%s\n",str);
      }
   }
   if(!done)
      done=1;
   SDL_KillThread(local_thread);
   return(0);
}


tcpmultiserver.c
Código:
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <SDL/SDL.h>
#include <SDL/SDL_net.h>
#include "tcputil.h"

typedef struct {
   TCPsocket sock;
   char *name;
} Client;

int running=1;
Client *clients=NULL;
int num_clients=0;
TCPsocket server;

#ifdef WIN32
#define strcasecmp _stricmp
#define strncasecmp _strnicmp

char *strsep(char **stringp, const char *delim)
{
   char *p;
   
   if(!stringp)
      return(NULL);
   p=*stringp;
   while(**stringp && !strchr(delim,**stringp))
      (*stringp)++;
   if(**stringp)
   {
      **stringp='\0';
      (*stringp)++;
   }
   else
      *stringp=NULL;
   return(p);
}

#endif

void send_all(char *buf);
int find_client_name(char *name);

/* this is a simplistic printf-like function the format only takes a string of */
/* chars that represent datatypes. */
/* it mallocs space and prints into that buffer. */
/* it uses a static pointer so that the user doesn't have to free the buffer */
char *mformat(char *format,...)
{
   va_list ap;
   Uint32 len=0;
   static char *str=NULL;
   char *p, *s;
   char c;
   int d;
   unsigned int u;

   if(str)
   {
      free(str);
      str=NULL;
   }
   if(!format)
      return(NULL);
   va_start(ap,format);
   for(p=format; *p; p++)
   {
      switch(*p)
      {
         case 's': /* string */
            s=va_arg(ap, char*);
            str=(char*)realloc(str,((len+strlen(s)+4)/4)*4);
            sprintf(str+len,"%s",s);
            break;
         case 'c': /* char */
            c=(char)va_arg(ap, int);
            str=(char*)realloc(str,len+4);
            sprintf(str+len,"%c",c);
            break;
         case 'd': /* int */
            d=va_arg(ap, int);
            str=(char*)realloc(str,((len+64)/4)*4);
            sprintf(str+len,"%d",d);
            break;
         case 'u': /* unsigned int */
            u=va_arg(ap, unsigned int);
            str=(char*)realloc(str,((len+64)/4)*4);
            sprintf(str+len,"%u",u);
            break;
      }
      /* set len to the new string length */
      if(str)
         len=strlen(str);
      else
         len=0;
   }
   va_end(ap);
   return(str);
}

/* terminate the nick at "bad" characters... */
void fix_nick(char *s)
{
   unsigned int i;

   if((i=strspn(s,"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ|_=+.,:;/\\?!@#$%^&*()~`"))!=strlen(s))
      s[i]='\0';
}

/* test for nice name uniqueness among already connected users */
int unique_nick(char *s)
{
   return(find_client_name(s)==-1);
}

/* add a client into our array of clients */
Client *add_client(TCPsocket sock, char *name)
{
   fix_nick(name);
   if(!strlen(name))
   {
      putMsg(sock,"Invalid Nickname...bye bye!");
      SDLNet_TCP_Close(sock);
      return(NULL);
   }
   if(!unique_nick(name))
   {
      putMsg(sock,"Duplicate Nickname...bye bye!");
      SDLNet_TCP_Close(sock);
      return(NULL);
   }
   clients=(Client*)realloc(clients, (num_clients+1)*sizeof(Client));
   clients[num_clients].name=name;
   clients[num_clients].sock=sock;
   num_clients++;
   /* server side info */
   printf("--> %s\n",name);
   /* inform all clients, including the new one, of the joined user */
   send_all(mformat("ss","--> ",name));
   return(&clients[num_clients-1]);
}

/* find a client in our array of clients by it's socket. */
/* the socket is always unique */
int find_client(TCPsocket sock)
{
   int i;
   for(i=0;i<num_clients;i++)
      if(clients[i].sock==sock)
         return(i);
   return(-1);
}

/* find a client in our array of clients by it's socket. */
/* the name is always unique */
int find_client_name(char *name)
{
   int i;
   for(i=0;i<num_clients;i++)
      if(!strcasecmp(clients[i].name,name))
         return(i);
   return(-1);
}

/* remove a client from our array of clients */
void remove_client(int i)
{
   char *name=clients[i].name;

   if(i<0 && i>=num_clients)
      return;
   
   /* close the old socket, even if it's dead... */
   SDLNet_TCP_Close(clients[i].sock);
   
   num_clients--;
   if(num_clients>i)
      memmove(&clients[i], &clients[i+1], (num_clients-i)*sizeof(Client));
   clients=(Client*)realloc(clients, num_clients*sizeof(Client));
   /* server side info */
   printf("<-- %s\n",name);
   /* inform all clients, excluding the old one, of the disconnected user */
   send_all(mformat("ss","<-- ",name));
   if(name)
      free(name);
}

/* create a socket set that has the server socket and all the client sockets */
SDLNet_SocketSet create_sockset()
{
   static SDLNet_SocketSet set=NULL;
   int i;

   if(set)
      SDLNet_FreeSocketSet(set);
   set=SDLNet_AllocSocketSet(num_clients+1);
   if(!set) {
      printf("SDLNet_AllocSocketSet: %s\n", SDLNet_GetError());
      exit(1); /*most of the time this is a major error, but do what you want. */
   }
   SDLNet_TCP_AddSocket(set,server);
   for(i=0;i<num_clients;i++)
      SDLNet_TCP_AddSocket(set,clients[i].sock);
   return(set);
}

/* send a buffer to all clients */
void send_all(char *buf)
{
   int cindex;

   if(!buf || !num_clients)
      return;
   cindex=0;
   while(cindex<num_clients)
   {
      /* putMsg is in tcputil.h, it sends a buffer over a socket */
      /* with error checking */
      if(putMsg(clients[cindex].sock,buf))
         cindex++;
      else
         remove_client(cindex);
   }
}

void do_command(char *msg, Client *client)
{
   char *command,*p;
   int len;

   if(!msg || !strlen(msg) || !client)
      return;
   len=strlen(msg);
   p=msg;
   command=strsep(&p," \t");
   /* /NICK : change the clients name */
   if(!strcasecmp(command,"NICK"))
   {
      if(p && strlen(p))
      {
         char *old_name=client->name;
         
         fix_nick(p);
         if(!strlen(p))
         {
            putMsg(client->sock,"--- Invalid Nickname!");
            return;
         }
         if(!unique_nick(p))
         {
            putMsg(client->sock,"--- Duplicate Nickname!");
            return;
         }
         client->name=strdup(p);
         send_all(mformat("ssss","--- ",old_name," --> ",p));
         free(old_name);
      }
      else
         putMsg(client->sock,"--- /NICK nickname");
      return;
   }
   /* MSG : client to client message */
   if(!strcasecmp(command,"MSG"))
   {
      char *name;
      int to;

      if(p)
      {
         name=strsep(&p," ");
         to=find_client_name(name);
         if(to<0)
         {
            putMsg(client->sock, mformat("sss","--- /MSG nickname ",name," not found!"));
            return;
         }
         else if(p && strlen(p))
         {
            putMsg(client->sock,mformat("ssss",">",clients[to].name,"< ",p));
            putMsg(clients[to].sock,mformat("ssss",">",client->name,"< ",p));
            return;
         }
      }
      putMsg(client->sock,"--- /MSG nickname message...");
      return;
   }
   /* /ME : emote! to everyone */
   if(!strcasecmp(command,"ME"))
   {
      if(p && strlen(p))
      {
         send_all(mformat("sss",client->name," ",p));
      }
      else
         putMsg(client->sock,"--- /ME message...");
      return;
   }
   /* /QUIT : quit the server with a message */
   if(!strcasecmp(command,"QUIT"))
   {
      if(!p || strcasecmp(p,"-h"))
      {
         if(p)
            send_all(mformat("ssss","--- ",client->name," quits : ",p));
         else
            send_all(mformat("sss","--- ",client->name," quits"));
         remove_client(find_client(client->sock));
      }
      else
         putMsg(client->sock,"--- /QUIT [message...]");
      return;
   }
   /* /WHO : list the users online back to the client */
   if(!strcasecmp(command,"WHO"))
   {
      int i;
      IPaddress *ipaddr;
      Uint32 ip;
      const char *host=NULL;
      
      putMsg(client->sock,"--- Begin /WHO ");
      for(i=0;i<num_clients;i++)
      {
         ipaddr=SDLNet_TCP_GetPeerAddress(clients[i].sock);
         if(ipaddr)
         {
            ip=SDL_SwapBE32(ipaddr->host);
            host=SDLNet_ResolveIP(ipaddr);
            putMsg(client->sock,mformat("sssssdsdsdsdsd","--- ",clients[i].name,
                  " ",host?host:"",
                  "[",ip>>24,".", (ip>>16)&0xff,".", (ip>>8)&0xff,".", ip&0xff,
                  "] port ",(Uint32)ipaddr->port));
         }
      }
      putMsg(client->sock,"--- End /WHO");
      return;
   }
   /* /HELP : tell the client all the supported commands */
   if(!strcasecmp(command,"HELP"))
   {
      putMsg(client->sock,"--- Begin /HELP");
      putMsg(client->sock,"--- /HELP : this text");
      putMsg(client->sock,"--- /ME message... : emote!");
      putMsg(client->sock,"--- /MSG nickname message... : personal messaging");
      putMsg(client->sock,"--- /NICK nickname : change nickaname");
      putMsg(client->sock,"--- /QUIT [message...] : disconnect this client");
      putMsg(client->sock,"--- /WHO : list who is logged on");
      putMsg(client->sock,"--- End /HELP");
      return;
   }

   /* invalid command...respond appropriately */
   putMsg(client->sock,mformat("sss","--- What does the '",command,"' command do?"));
}

int main(int argc, char **argv)
{
   IPaddress ip;
   TCPsocket sock;
   SDLNet_SocketSet set;
   char *message=NULL;
   const char *host=NULL;
   Uint32 ipaddr;
   Uint16 port;
   
   /* check our commandline */
   if(argc<2)
   {
      printf("%s port\n",argv[0]);
      exit(0);
   }
   
   /* initialize SDL */
   if(SDL_Init(0)==-1)
   {
      printf("SDL_Init: %s\n",SDL_GetError());
      exit(1);
   }

   /* initialize SDL_net */
   if(SDLNet_Init()==-1)
   {
      printf("SDLNet_Init: %s\n",SDLNet_GetError());
      SDL_Quit();
      exit(2);
   }

   /* get the port from the commandline */
   port=(Uint16)strtol(argv[1],NULL,0);

   /* Resolve the argument into an IPaddress type */
   if(SDLNet_ResolveHost(&ip,NULL,port)==-1)
   {
      printf("SDLNet_ResolveHost: %s\n",SDLNet_GetError());
      SDLNet_Quit();
      SDL_Quit();
      exit(3);
   }

   /* perform a byte endianess correction for the next printf */
   ipaddr=SDL_SwapBE32(ip.host);

   /* output the IP address nicely */
   printf("IP Address : %d.%d.%d.%d\n",
         ipaddr>>24,
         (ipaddr>>16)&0xff,
         (ipaddr>>8)&0xff,
         ipaddr&0xff);

   /* resolve the hostname for the IPaddress */
   host=SDLNet_ResolveIP(&ip);

   /* print out the hostname we got */
   if(host)
      printf("Hostname   : %s\n",host);
   else
      printf("Hostname   : N/A\n");

   /* output the port number */
   printf("Port       : %d\n",port);

   /* open the server socket */
   server=SDLNet_TCP_Open(&ip);
   if(!server)
   {
      printf("SDLNet_TCP_Open: %s\n",SDLNet_GetError());
      SDLNet_Quit();
      SDL_Quit();
      exit(4);
   }

   while(1)
   {
      int numready,i;
      set=create_sockset();
      numready=SDLNet_CheckSockets(set, (Uint32)-1);
      if(numready==-1)
      {
         printf("SDLNet_CheckSockets: %s\n",SDLNet_GetError());
         break;
      }
      if(!numready)
         continue;
      if(SDLNet_SocketReady(server))
      {
         numready--;
         /*printf("Connection...\n"); */
         sock=SDLNet_TCP_Accept(server);
         if(sock)
         {
            char *name=NULL;

            /*printf("Accepted...\n"); */
            if(getMsg(sock, &name))
            {
               Client *client;
               client=add_client(sock,name);
               if(client)
                  do_command("WHO",client);
            }
            else
               SDLNet_TCP_Close(sock);
         }
      }
      for(i=0; numready && i<num_clients; i++)
      {
         if(SDLNet_SocketReady(clients[i].sock))
         {
            if(getMsg(clients[i].sock, &message))
            {
               char *str;
               
               numready--;
               printf("<%s> %s\n",clients[i].name,message);
               /* interpret commands */
               if(message[0]=='/' && strlen(message)>1)
               {
                  do_command(message+1,&clients[i]);
               }
               else /* it's a regular message */
               {
                  /* forward message to ALL clients... */
                  str=mformat("ssss","<",clients[i].name,"> ",message);
                  if(str)
                     send_all(str);
               }
               free(message);
               message=NULL;
            }
            else
               remove_client(i);
         }
      }
   }

   /* shutdown SDL_net */
   SDLNet_Quit();

   /* shutdown SDL */
   SDL_Quit();

   return(0);
}


Y el mensioado tcputil.h
Código:
#ifndef tcputil_h
#define tcputil_h 1

#include <SDL/SDL.h>
#include <SDL/SDL_net.h>

/* receive a buffer from a TCP socket with error checking */
/* this function handles the memory, so it can't use any [] arrays */
/* returns 0 on any errors, or a valid char* on success */
char *getMsg(TCPsocket sock, char **buf)
{
   Uint32 len,result;
   static char *_buf;

   /* allow for a NULL buf, use a static internal one... */
   if(!buf)
      buf=&_buf;
   
   /* free the old buffer */
   if(*buf)
      free(*buf);
   *buf=NULL;

   /* receive the length of the string message */
   result=SDLNet_TCP_Recv(sock,&len,sizeof(len));
   if(result<sizeof(len))
   {
      if(SDLNet_GetError() && strlen(SDLNet_GetError())) /* sometimes blank! */
         printf("SDLNet_TCP_Recv: %s\n", SDLNet_GetError());
      return(NULL);
   }
   
   /* swap byte order to our local order */
   len=SDL_SwapBE32(len);
   
   /* check if anything is strange, like a zero length buffer */
   if(!len)
      return(NULL);

   /* allocate the buffer memory */
   *buf=(char*)malloc(len);
   if(!(*buf))
      return(NULL);

   /* get the string buffer over the socket */
   result=SDLNet_TCP_Recv(sock,*buf,len);
   if(result<len)
   {
      if(SDLNet_GetError() && strlen(SDLNet_GetError())) /* sometimes blank! */
         printf("SDLNet_TCP_Recv: %s\n", SDLNet_GetError());
      free(*buf);
      buf=NULL;
   }

   /* return the new buffer */
   return(*buf);
}

/* send a string buffer over a TCP socket with error checking */
/* returns 0 on any errors, length sent on success */
int putMsg(TCPsocket sock, char *buf)
{
   Uint32 len,result;

   if(!buf || !strlen(buf))
      return(1);

   /* determine the length of the string */
   len=strlen(buf)+1; /* add one for the terminating NULL */
   
   /* change endianness to network order */
   len=SDL_SwapBE32(len);

   /* send the length of the string */
   result=SDLNet_TCP_Send(sock,&len,sizeof(len));
   if(result<sizeof(len)) {
      if(SDLNet_GetError() && strlen(SDLNet_GetError())) /* sometimes blank! */
         printf("SDLNet_TCP_Send: %s\n", SDLNet_GetError());
      return(0);
   }
   
   /* revert to our local byte order */
   len=SDL_SwapBE32(len);
   
   /* send the buffer, with the NULL as well */
   result=SDLNet_TCP_Send(sock,buf,len);
   if(result<len) {
      if(SDLNet_GetError() && strlen(SDLNet_GetError())) /* sometimes blank! */
         printf("SDLNet_TCP_Send: %s\n", SDLNet_GetError());
      return(0);
   }
   
   /* return the length sent */
   return(result);
}

#endif
Volver arriba
      Índice del Foro elrincondelc.com -> Programación en Servidores
Página 1 de 1Todas las horas están en GMT - 8 Horas

 
No puede crear mensajes
No puede responder temas
No puede editar sus mensajes
No puede borrar sus mensajes
No puede votar en encuestas

(c) ElRincondelC.com

Un proyecto de UrlanHeat.com