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