Networking Game Code for Linux


In my early article I had some networking code. In this article I have code that I am going to use for my game. There is a lot of stuff you can play with. I used pthreads, mutexes, a simple messaging queue. And a host of other goodies. I have included the main part, the source can be downloaded from here.
Netcode
>//
// Berlin Brown
// bigbinc@hotmail.com
//
// - client code 
//
// network.c
// - c network routines
//
// linux version gcc 2.96/ mandrake 8.2
//
// Note: run /etc/services for empty ports
//
#include 
#include 
#include 
#include 
#include  // posix threads

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "../include/msg.h"
#include "network.h"

#define SNIFFER_OFF                     0
#define SNIFFER_ON                      1

#define MAX_SIZE 80

extern struct sockaddr *client_addie;

static int flag = 0;
static pthread_t thread_id[2];

#define CONNECT_STR "127.0.0.1"
#define CONNECT_PORT 9000


struct timeval  now;            
struct timespec timeout;        


//
// sniffer variables
pthread_mutex_t snifferMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t snifferCond = PTHREAD_COND_INITIALIZER; 
pthread_attr_t attr;

static int sniffer_flag = SNIFFER_OFF;
static int sniffer_state = SNIFFER_OFF;


//
// Create_Mutex()
void Create_Mutex(void)
{
  pthread_mutex_init(&snifferMutex,NULL);

  // also create condition
  pthread_cond_init(&snifferCond, NULL);

  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

} // end of the function 

//
// Destroy Mutex
void Destroy_Mutex(void)
{
  
  pthread_mutex_destroy(&snifferMutex);
  pthread_cond_destroy(&snifferCond);

} // end of the function

//
// WaitChar
//
void WaitChar(void)
{
  getchar();

  flag = 1;
  
} // end of the function 

//
// WaitThread
//
void WaitThread(void)
{

  int status;
  int i;
  int res;

  pthread_attr_destroy(&attr);

  for (i = 0; i < 2; i++)
    {
      // blocked call
      res = pthread_join(thread_id[i],(void **)&status);  // Parent waits for 
      
      pthread_cancel(thread_id[1]);
      printf("join complete, killing thread 2\n");
      break;

    } // end of the for 

} // end of the function 


//
// Lock_Sniffer()
//
static void Lock_Sniffer(void)
{
  sniffer_flag = SNIFFER_ON;
} // end of func

//
// unlock
static void Unlock_Sniffer(void)
{
  sniffer_flag = SNIFFER_OFF;
} // end of func

//
// another thread function
//
void *SnifferThread(void *args)
{
  int res;
  res = 0;

  // main while loop 
  while(1) {

    if (sniffer_state == SNIFFER_OFF) {

      if (sniffer_flag == SNIFFER_ON)
	{
	  // flag is set restart the timer
	  sniffer_state = SNIFFER_ON;

	  // reset collection flag --
	  sniffer_flag = SNIFFER_OFF;

	  // collect a new timeout
	    gettimeofday(&now, NULL);
	    timeout.tv_sec = now.tv_sec + ALARM_TIMEOUT;
	    timeout.tv_nsec = now.tv_usec * 1000;
	
	} // end of the if 
  
    } else {

      // sniffer state is going

      pthread_mutex_lock(&snifferMutex);
      while(1) {
	
	// note, this is another blocked call in addition to recvfrom
	
	// res returns zero is based on condition
	res = pthread_cond_timedwait(&snifferCond, &snifferMutex, &timeout);
	if (res == ETIMEDOUT) {

	  // kill the other thread
	  sniffer_state = SNIFFER_OFF;
	  pthread_cancel(thread_id[0]);
	  printf("timer was released, killing thread\n");
	  
	  break;
	} // end of the if 
	
      
      } // end of while
      pthread_mutex_unlock(&snifferMutex);
      
    }  // end of if - else

    // continue with sniffer agent

  } // endof while --

} // end of the function 


void *WaitMsg(void *args)
{
  char buffer[80];
  int bytes_recv;
  int sock;
  struct sockaddr_in from_addr;
  unsigned int addr_size;

  Msg msg;
  void *buf = NULL;


  // set the pointer
  buf = (void *)&msg;


  // get the socket data
  sock = ((ComObjPtr)args)->sock;

      bytes_recv = 0;
#if defined(UDP_PROTOCOL)
      
      addr_size = sizeof(from_addr);


      Lock_Sniffer();
      
      bytes_recv = recvfrom(sock, buffer, MAX_SIZE, 0,
			    (struct sockaddr *)&from_addr, &addr_size);

      Unlock_Sniffer();

#else
      addr_size = 0;
      
      bytes_recv = recv(sock, buffer, MAX_SIZE, 0);
#endif

      buffer[bytes_recv] = '\0';  
      printf(buffer);

      // 
      // get the new msg data 
      //
#if defined(UDP_PROTOCOL)
      
      addr_size = sizeof(from_addr);
      bytes_recv = recvfrom(sock, buf, sizeof(Msg), 0,
			    (struct sockaddr *)&from_addr, &addr_size);
		    
#else
      addr_size = 0;      
      bytes_recv = recv(sock, buf, sizeof(Msg), 0);
#endif

      printf("%d %0.2f 1time\n", msg.msg_id, msg.pos_x);
    

      // trick number 3
      // collect an array of msgs

     
#if defined(UDP_PROTOCOL)
      
      buf = GetMsgCluster();
      addr_size = sizeof(from_addr);

      bytes_recv = recvfrom(sock, buf, 3*sizeof(Msg), 0,
			    (struct sockaddr *)&from_addr, &addr_size);
		    
#else
      addr_size = 0;      
      bytes_recv = recv(sock, buf, sizeof(Msg), 0);
#endif
    
      Print_MsgTest();

      // assume udp
      // and still a little more left
      //Send_Net_Packet(sock, sock);
      //Recv_Net_Packet(sock, sock);
    

      if (flag) {
	pthread_exit(NULL);
      } // end of the if 
 
 
      pthread_exit(NULL);

  return NULL;
} // end of the function 

//
// Connect
//
void Connect(ComObjPtr com_obj, char *ip, int port)
{
  int res; 
  struct sockaddr_in serv_addr;

  strcpy(com_obj->ipaddress, ip);
  com_obj->port = port;

#if defined(UDP_PROTOCOL)
  com_obj->sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
#else
  com_obj->sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
#endif
 
  if (com_obj->sock < 0)
    {
      fprintf(stderr, "socket() failed\n");
      exit(1);
    } // end of the if 
  
  // construct server address
  memset(&serv_addr, 0, sizeof(serv_addr));

  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = inet_addr(com_obj->ipaddress);
  serv_addr.sin_port = htons(com_obj->port);


#if defined(TCP_PROTOCOL)
  // establish connection to the echo server --
  res = connect(com_obj->sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
  
  if (res < 0)
    {
      fprintf(stderr, "connect() failed\n");
      exit(1);
    } // end of if
#endif 

  strcpy(com_obj->msg, "Hello man\n");

  // send the string
  com_obj->msg_size = strlen(com_obj->msg);
  

#if defined(UDP_PROTOCOL)
  res = sendto(com_obj->sock, com_obj->msg, com_obj->msg_size, 0, 
	       (struct sockaddr *)&serv_addr, sizeof(serv_addr));
#else
  res = send(com_obj->sock, com_obj->msg, com_obj->msg_size, 0);  
#endif

  client_addie = (struct sockaddr *)&serv_addr;

  // timeout variables and init functions
  Create_Mutex();

 
  // create a sniffer agent thread also
  pthread_create(&thread_id[1], &attr, SnifferThread, NULL); 

  // also recv a message 
  // create a thread to wait for messages
  pthread_create(&thread_id[0], &attr, WaitMsg, (void *)com_obj);

  
} // end of the function 

//
// RunTest
//
void RunTest(void)
{
  char buffer[80];
  ComObjPtr com_obj;

  com_obj = malloc(sizeof(ComObj));
  
  Connect(com_obj, CONNECT_STR, CONNECT_PORT);  
  //WaitChar();
  WaitThread();

  Destroy_Mutex();

  Start_Net_Time();      

  memset(buffer, 'c', 64*sizeof(char));
  buffer[64]='\0';
  sendto(com_obj->sock,buffer , strlen(buffer), 0, 
	       (struct sockaddr *)client_addie, sizeof(struct sockaddr));  

  End_Net_Time();
  Print_Net_Time();

  
  close(com_obj->sock);
  free(com_obj);

} // end of the function