Pong Game - Trouble using sockets
I've been working on this project for over a week (giving it time when I have it). This is the first time posting on a forum for help (I can usually figure things out). What I need this to do is have two players play the game pong with one another over the internet. One player (the first one) is the "server" and the second player is the "client" and that is the relationship both instances have. I just got into sockets a couple weeks ago and am having a lot of difficulty understanding exactly how to use them for this (been reading a couple unix books and googling). I'm trying to figure out how to get the ball information when it hits the "net" (that shows up on both screens) through the socket to the other instance of the program running so that the ball will show up on the other player's court (each player only sees their side of the court).
Server player calls program with 1 argument (the port number) and the client player calls the program with 2 arguments (the server address and port number).
Yes, this was a project that was due this past Thursday. My professor would still like to see me do this. (It was for an independent study course)
This code is primarily being run on a solaris server and I telnet in. I also run it on ubuntu.
I apologize for not cutting down the code at all, but I couldn't figure out a way that would make it easier to read. Any and all help/suggestions are appreciated!
netpong.c
Code:
#include <curses.h>
#include <signal.h>
#include "bounce.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <time.h>
#include <strings.h>
#include <fcntl.h>
struct ppball the_ball;
struct pppaddle the_paddle;
char horizwall[] = "---------------------------------------------------------------";
char halfhorizwall[] = "-------------------------------";
char vertwall[] = "|";
char net[] = ".";
int balls_left = 3;
/** the main loop **/
int get_rand(int, int);
void set_up();
void client_set_up();
void server_set_up();
void serve();
void client_serve();
void server_serve();
void wrap_up();
#define oops(msg) { perror(msg) ; exit(1) ; }
int main (int argc, char* argv[])
{
int c;
if( argc == 2 ) // is server
{
struct sockaddr_in saddr;
struct hostent *hp;
char hostname[256];
int sock_id,sock_fd,flags;
FILE *sock_fp;
sock_id = socket( PF_INET, SOCK_STREAM, 0 ); /* get a socket */
if ( sock_id == -1 )
oops( "socket" );
bzero( (void *)&saddr, sizeof(saddr) ); /* clear out struct */
gethostname( hostname, 256 );
hp = gethostbyname( hostname );
bcopy( (void *)hp->h_addr, (void *)&saddr.sin_addr, hp->h_length);
saddr.sin_port = htons(atoi(argv[1]));
saddr.sin_family = AF_INET;
if ( bind(sock_id, (struct sockaddr *)&saddr, sizeof(saddr)) != 0 )
oops( "bind" );
if ( listen(sock_id, 1) != 0 )
oops( "listen" );
while ( 1 ){
sock_fd = accept(sock_id, NULL, NULL);
printf("Wow! got a call!\n");
if ( sock_fd == -1 )
oops( "accept" );
flags = fcntl(sock_fd, F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(sock_fd, F_SETFL, flags);
sock_fp = fdopen(sock_fd,"w");
if ( sock_fp == NULL )
oops( "fdopen" );
fprintf( sock_fp, "Client connected to the server!\n" );
switch ( fork() ) {
case -1:
oops("fork");
case 0:
close(sock_fd);
exit(0);
default:
server_set_up();
server_serve();
while( balls_left > 0 && ( c = getchar()) != 'Q' ){
if ( c == 'j' ) paddle_down();
else if ( c == 'k' ) paddle_up();
}
wrap_up();
fclose( sock_fp );
}
}
}
else if( argc == 3 ) // is client
{
struct sockaddr_in servadd;
struct hostent *hp;
int sock_id, sock_fd;
char message[BUFSIZ];
int messlen;
int i;
sock_id = socket( AF_INET, SOCK_STREAM, 0 ); /* get a line */
if ( sock_id == -1 )
oops( "socket" );
bzero( &servadd, sizeof( servadd ) );
hp = gethostbyname( argv[1] );
bcopy(hp->h_addr, (struct sockaddr *)&servadd.sin_addr, hp->h_length);
servadd.sin_port = htons(atoi(argv[2]));
servadd.sin_family = AF_INET;
if ( connect(sock_id,(struct sockaddr *)&servadd, sizeof(servadd)) !=0)
oops( "connect" );
messlen = read(sock_id, message, BUFSIZ);
if ( messlen == - 1 )
oops("read") ;
if ( write( 1, message, messlen ) != messlen )
oops( "write" );
client_set_up();
client_serve();
while( balls_left > 0 && ( c = getchar()) != 'Q' ){
if ( c == 'j' ) paddle_down();
else if ( c == 'k' ) paddle_up();
}
wrap_up();
close( sock_id );
}
else
{
printf("Playing regular pong!\n");
sleep(3);
set_up();
serve();
while( balls_left > 0 && ( c = getchar()) != 'Q' ){
if ( c == 'j' ) paddle_down();
else if ( c == 'k' ) paddle_up();
}
wrap_up();
}
}
void set_up()
/*
* init structure and other stuff
*/
{
int i;
initscr();
noecho();
crmode();
/* Building walls */
move(4,9);
addstr(horizwall);
move(21,9);
addstr(horizwall);
for( i = 5; i < 21; i++ )
{
move(i,9);
addstr(vertwall);
}
paddle_init();
refresh();
}
void client_set_up()
/*
* init structure and other stuff
*/
{
int i;
initscr();
noecho();
crmode();
/* Building walls */
move(4,9);
addstr(halfhorizwall);
move(21,9);
addstr(halfhorizwall);
for( i = 5; i < 21; i++ )
{
move(i,9);
addstr(net);
}
move(22,9);
addstr("Me:");
move(22,16);
addstr("Server:");
paddle_client_init();
refresh();
}
void server_set_up()
/*
* init structure and other stuff
*/
{
int i;
initscr();
noecho();
crmode();
/* Building walls */
move(4,31);
addstr(halfhorizwall);
move(21,31);
addstr(halfhorizwall);
for( i = 5; i < 21; i++ )
{
move(i,61);
addstr(net);
}
move(22,31);
addstr("Me:");
move(22,38);
addstr("Client:");
paddle_server_init();
refresh();
}
void serve()
{
void ball_move(int);
/* Random values for initial position and speed */
//int y_pos_r = ( rand() % (19 - 6 + 1) + 6 );
int y_pos_r = get_rand(6, 19);
int x_pos_r = get_rand(11, 68);
int y_ttm_r = get_rand(4, 16);
int x_ttm_r = get_rand(4, 16);
the_ball.y_pos = y_pos_r;
the_ball.x_pos = x_pos_r;
the_ball.y_ttg = the_ball.y_ttm = y_ttm_r ;
the_ball.x_ttg = the_ball.x_ttm = x_ttm_r ;
the_ball.y_dir = 1 ;
the_ball.x_dir = 1 ;
the_ball.symbol = DFL_SYMBOL;
signal( SIGINT , SIG_IGN );
mvaddch( the_ball.y_pos, the_ball.x_pos, the_ball.symbol );
refresh();
signal( SIGALRM, ball_move );
set_ticker( 1000 / TICKS_PER_SEC ); /* send millisecs per tick */
}
void client_serve()
{
void client_ball_move(int);
/* Random values for initial position and speed */
//int y_pos_r = ( rand() % (19 - 6 + 1) + 6 );
int y_pos_r = get_rand(6, 19);
int x_pos_r = get_rand(11, 38);
int y_ttm_r = get_rand(4, 16);
int x_ttm_r = get_rand(4, 16);
the_ball.y_pos = y_pos_r;
the_ball.x_pos = x_pos_r;
the_ball.y_ttg = the_ball.y_ttm = y_ttm_r ;
the_ball.x_ttg = the_ball.x_ttm = x_ttm_r ;
the_ball.y_dir = 1 ;
the_ball.x_dir = 1 ;
the_ball.symbol = DFL_SYMBOL;
signal( SIGINT , SIG_IGN );
mvaddch( the_ball.y_pos, the_ball.x_pos, the_ball.symbol );
refresh();
signal( SIGALRM, client_ball_move );
set_ticker( 1000 / TICKS_PER_SEC ); /* send millisecs per tick */
}
void server_serve()
{
void server_ball_move(int);
/* Random values for initial position and speed */
//int y_pos_r = ( rand() % (19 - 6 + 1) + 6 );
int y_pos_r = get_rand(6, 19);
int x_pos_r = get_rand(31, 58);
int y_ttm_r = get_rand(4, 16);
int x_ttm_r = get_rand(4, 16);
the_ball.y_pos = y_pos_r;
the_ball.x_pos = x_pos_r;
the_ball.y_ttg = the_ball.y_ttm = y_ttm_r ;
the_ball.x_ttg = the_ball.x_ttm = x_ttm_r ;
the_ball.y_dir = 1 ;
the_ball.x_dir = 1 ;
the_ball.symbol = DFL_SYMBOL;
signal( SIGINT , SIG_IGN );
mvaddch( the_ball.y_pos, the_ball.x_pos, the_ball.symbol );
refresh();
signal( SIGALRM, server_ball_move );
set_ticker( 1000 / TICKS_PER_SEC ); /* send millisecs per tick */
}
void wrap_up()
{
set_ticker( 0 );
endwin(); /* put back to normal */
}
int get_rand(int min, int max)
{
return ( rand() % (max - min + 1) + min );
}
void ball_move(int signum)
{
int y_cur, x_cur, moved;
signal( SIGALRM , SIG_IGN ); /* dont get caught now */
y_cur = the_ball.y_pos ; /* old spot */
x_cur = the_ball.x_pos ;
moved = 0 ;
if ( the_ball.y_ttm > 0 && the_ball.y_ttg-- == 1 ){
the_ball.y_pos += the_ball.y_dir ; /* move */
the_ball.y_ttg = the_ball.y_ttm ; /* reset*/
moved = 1;
}
if ( the_ball.x_ttm > 0 && the_ball.x_ttg-- == 1 ){
the_ball.x_pos += the_ball.x_dir ; /* move */
the_ball.x_ttg = the_ball.x_ttm ; /* reset*/
moved = 1;
}
if ( moved ){
mvaddch( y_cur, x_cur, BLANK );
mvaddch( y_cur, x_cur, BLANK );
mvaddch( the_ball.y_pos, the_ball.x_pos, the_ball.symbol );
if( bounce_or_lose( &the_ball ) == -1 ){
mvaddch( the_ball.y_pos, the_ball.x_pos, BLANK );
sleep(1);
serve();
}
move(LINES-1,COLS-1);
refresh();
}
signal( SIGALRM, ball_move); /* for unreliable systems */
}
void client_ball_move(int signum)
{
int y_cur, x_cur, moved;
signal( SIGALRM , SIG_IGN ); /* dont get caught now */
y_cur = the_ball.y_pos ; /* old spot */
x_cur = the_ball.x_pos ;
moved = 0 ;
if ( the_ball.y_ttm > 0 && the_ball.y_ttg-- == 1 ){
the_ball.y_pos += the_ball.y_dir ; /* move */
the_ball.y_ttg = the_ball.y_ttm ; /* reset*/
moved = 1;
}
if ( the_ball.x_ttm > 0 && the_ball.x_ttg-- == 1 ){
the_ball.x_pos += the_ball.x_dir ; /* move */
the_ball.x_ttg = the_ball.x_ttm ; /* reset*/
moved = 1;
}
if ( moved ){
mvaddch( y_cur, x_cur, BLANK );
mvaddch( y_cur, x_cur, BLANK );
mvaddch( the_ball.y_pos, the_ball.x_pos, the_ball.symbol );
if( client_bounce_or_lose( &the_ball ) == -1 ){
mvaddch( the_ball.y_pos, the_ball.x_pos, BLANK );
sleep(1);
client_serve();
}
move(LINES-1,COLS-1);
refresh();
}
signal( SIGALRM, client_ball_move); /* for unreliable systems */
}
void server_ball_move(int signum)
{
int y_cur, x_cur, moved;
signal( SIGALRM , SIG_IGN ); /* dont get caught now */
y_cur = the_ball.y_pos ; /* old spot */
x_cur = the_ball.x_pos ;
moved = 0 ;
if ( the_ball.y_ttm > 0 && the_ball.y_ttg-- == 1 ){
the_ball.y_pos += the_ball.y_dir ; /* move */
the_ball.y_ttg = the_ball.y_ttm ; /* reset*/
moved = 1;
}
if ( the_ball.x_ttm > 0 && the_ball.x_ttg-- == 1 ){
the_ball.x_pos += the_ball.x_dir ; /* move */
the_ball.x_ttg = the_ball.x_ttm ; /* reset*/
moved = 1;
}
if ( moved ){
mvaddch( y_cur, x_cur, BLANK );
mvaddch( y_cur, x_cur, BLANK );
mvaddch( the_ball.y_pos, the_ball.x_pos, the_ball.symbol );
if( server_bounce_or_lose( &the_ball ) == -1 ){
mvaddch( the_ball.y_pos, the_ball.x_pos, BLANK );
sleep(1);
server_serve();
}
move(LINES-1,COLS-1);
refresh();
}
signal( SIGALRM, server_ball_move); /* for unreliable systems */
}
int bounce_or_lose(struct ppball *bp)
{
int return_val = 0 ;
if ( bp->y_pos == TOP_ROW ){
bp->y_dir = 1 ;
return_val = 1 ;
} else if ( bp->y_pos == BOT_ROW ){
bp->y_dir = -1 ;
return_val = 1;
}
if ( bp->x_pos == LEFT_EDGE ){
bp->x_dir = 1 ;
return_val = 1 ;
} else if ( bp->x_pos == RIGHT_EDGE ){
if( paddle_contact(bp->y_pos,bp->x_pos) == 0 ){
bp->x_dir = -1;
the_ball.y_ttm = get_rand(4, 16);
the_ball.x_ttm = get_rand(4, 16);
return_val = 1; // still in!
}
else{
balls_left--;
return_val = -1; // lose!
}
}
return return_val;
}
int client_bounce_or_lose(struct ppball *bp)
{
int return_val = 0 ;
if ( bp->y_pos == TOP_ROW ){
bp->y_dir = 1 ;
return_val = 1 ;
} else if ( bp->y_pos == BOT_ROW ){
bp->y_dir = -1 ;
return_val = 1;
}
if ( bp->x_pos == CLIENT_LEFT_EDGE ){
bp->x_dir = 1 ;
return_val = 1 ;
} else if ( bp->x_pos == CLIENT_RIGHT_EDGE ){
if( client_paddle_contact(bp->y_pos,bp->x_pos) == 0 ){
bp->x_dir = -1;
the_ball.y_ttm = get_rand(4, 16);
the_ball.x_ttm = get_rand(4, 16);
return_val = 1; // still in!
}
else{
balls_left--;
return_val = -1; // lose!
}
}
return return_val;
}
int server_bounce_or_lose(struct ppball *bp)
{
int return_val = 0 ;
if ( bp->y_pos == TOP_ROW ){
bp->y_dir = 1 ;
return_val = 1 ;
} else if ( bp->y_pos == BOT_ROW ){
bp->y_dir = -1 ;
return_val = 1;
}
if ( bp->x_pos == SERVER_RIGHT_EDGE ){
bp->x_dir = -1 ;
return_val = 1 ;
} else if ( bp->x_pos == SERVER_LEFT_EDGE ){
if( server_paddle_contact(bp->y_pos,bp->x_pos) == 0 ){
bp->x_dir = 1;
the_ball.y_ttm = get_rand(4, 16);
the_ball.x_ttm = get_rand(4, 16);
return_val = 1; // still in!
}
else{
balls_left--;
return_val = -1; // lose!
}
}
return return_val;
}
paddle.c
Code:
#include "bounce.h"
#include <curses.h>
struct pppaddle the_paddle;
int i, j;
paddle_init()
{
the_paddle.pad_char = PAD_SYMBOL;
/* top paddle >= row 5 and bottom paddle <= row 20 */
/* paddle col = 70 */
the_paddle.pad_col = 71;
the_paddle.pad_top = 10;
the_paddle.pad_bot = 15;
i = the_paddle.pad_top;
for( i; i <= the_paddle.pad_bot; i++ ){
mvaddch(i, the_paddle.pad_col, the_paddle.pad_char);
}
}
paddle_client_init()
{
the_paddle.pad_char = PAD_SYMBOL;
/* top paddle >= row 5 and bottom paddle <= row 20 */
/* paddle col = 39 */
the_paddle.pad_col = 40;
the_paddle.pad_top = 10;
the_paddle.pad_bot = 15;
i = the_paddle.pad_top;
for( i; i <= the_paddle.pad_bot; i++ ){
mvaddch(i, the_paddle.pad_col, the_paddle.pad_char);
}
}
paddle_server_init()
{
the_paddle.pad_char = PAD_SYMBOL;
/* top paddle >= row 5 and bottom paddle <= row 20 */
/* paddle col = 31 */
the_paddle.pad_col = 30;
the_paddle.pad_top = 10;
the_paddle.pad_bot = 15;
i = the_paddle.pad_top;
for( i; i <= the_paddle.pad_bot; i++ ){
mvaddch(i, the_paddle.pad_col, the_paddle.pad_char);
}
}
paddle_up()
{
if( the_paddle.pad_top >= 6 ){
mvaddch(the_paddle.pad_bot, the_paddle.pad_col, BLANK);
the_paddle.pad_top--;
the_paddle.pad_bot--;
i = the_paddle.pad_top;
for( i; i <= the_paddle.pad_bot; i++ ){
mvaddch(i, the_paddle.pad_col, the_paddle.pad_char);
}
}
}
paddle_down()
{
if( the_paddle.pad_bot < 20 ){
mvaddch(the_paddle.pad_top, the_paddle.pad_col, BLANK);
the_paddle.pad_top++;
the_paddle.pad_bot++;
i = the_paddle.pad_top;
for( i; i <= the_paddle.pad_bot; i++ ){
mvaddch(i, the_paddle.pad_col, the_paddle.pad_char);
}
}
}
paddle_contact(y, x)
{
/* Returns 0 if true and 1 if false */
if( x == 70 ){
j = the_paddle.pad_top;
for( j; j <= the_paddle.pad_bot; j++ ){
if( y == j ){
return 0;
}
}
}
return -1;
}
client_paddle_contact(y, x)
{
/* Returns 0 if true and 1 if false */
if( x == 39 ){
j = the_paddle.pad_top;
for( j; j <= the_paddle.pad_bot; j++ ){
if( y == j ){
return 0;
}
}
}
return -1;
}
server_paddle_contact(y, x)
{
/* Returns 0 if true and 1 if false */
if( x == 31 ){
j = the_paddle.pad_top;
for( j; j <= the_paddle.pad_bot; j++ ){
if( y == j ){
return 0;
}
}
}
return -1;
}
set_ticker.c
Code:
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
/*
* set_ticker.c
* set_ticker( number_of_milliseconds )
* arranges for the interval timer to issue
* SIGALRM's at regular intervals
* returns -1 on error, 0 for ok
*
* arg in milliseconds, converted into micro seoncds
*/
set_ticker( n_msecs )
{
struct itimerval new_timeset;
long n_sec, n_usecs;
n_sec = n_msecs / 1000 ;
n_usecs = ( n_msecs % 1000 ) * 1000L ;
new_timeset.it_interval.tv_sec = n_sec; /* set reload */
new_timeset.it_interval.tv_usec = n_usecs; /* new ticker value */
new_timeset.it_value.tv_sec = n_sec ; /* store this */
new_timeset.it_value.tv_usec = n_usecs ; /* and this */
return setitimer(ITIMER_REAL, &new_timeset, NULL);
}
bounce.h
Code:
/* bounce.h */
/* some settings for the game */
#define BLANK ' '
#define DFL_SYMBOL 'o'
#define PAD_SYMBOL '#'
#define TOP_ROW 5
#define BOT_ROW 20
#define LEFT_EDGE 10
#define CLIENT_LEFT_EDGE 10
#define SERVER_LEFT_EDGE 30
#define RIGHT_EDGE 70
#define CLIENT_RIGHT_EDGE 40
#define SERVER_RIGHT_EDGE 60
#define X_INIT 10 /* starting col */
#define Y_INIT 10 /* starting row */
#define TICKS_PER_SEC 50 /* affects speed */
#define X_TTM 5
#define Y_TTM 8
/** the ping pong ball **/
struct ppball{
int y_pos, x_pos,
y_ttm, x_ttm,
y_ttg, x_ttg,
y_dir, x_dir;
char symbol ;
};
/** the ping pong paddle **/
struct pppaddle{
int pad_top, pad_bot, pad_col;
char pad_char;
};
makefile script
Code:
gcc -o netpong netpong.c paddle.c set_ticker.c -lcurses -lsocket -lnsl