Sign in to follow this  

a tough question to phrase

This topic is 4597 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I want to be able to send/recv packets of information between my game and my server, while performing other actions (ex. typing a message). I just cant understand how to do it. In my current program, i can recv packets or type. And untill I'm done typing, no packets can get through. I want the option to type a message to be avalible all the time, and I cant afford to not recv packets because I am typing. The program is using TCP, I cant think of anyway that could help, but I felt like typing it. I know it is possible to do, because I've seen it done, but I don't get the philosophy behind it. Thanks in advance for all replies... Happy coders. [grin]

Share this post


Link to post
Share on other sites
What you are refering to is non-blocking input/output.

Say you have something like this:

forever
read character from input
send character to socket
do other stuff

When you read a character you normally 'get stuck' in the call until data is available, until a user hits a key on the keyboard in this case.

What you want is some this kind of logic:

forever
if character from input avalable?
read input
send character to socket
do other stuff

This way you can do your other stuff without waiting for the user to type a character.

The concept of non-blocking IO can also be applied to sockets and all other types of IO interaces.

On UNIX you can use select() to check if any data is avalable on sockets, stdio and files. I don't know how this is for Windows though.

Share this post


Link to post
Share on other sites
If you want to type, asynchronously, on UNIX, you need to set the TTY driver in un-buffered mode, and use non-blocking reads (or select()) to check for input. This is hugely more complicated that it "ought" to be, because of the 1970 teletype heritage of UNIX.

This is the source to a simple serial port communication program I wrote a while back. You may want to steal the functions setupser() and friends.


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <termios.h>


#define BAUD B19200

struct portinfo_t {
int fd_in;
int fd_out;
struct termios in_orig;
struct termios in_nu;
struct termios out_orig;
struct termios out_nu;
};

int
openser( char const * port, portinfo_t * info )
{
info->fd_out = -1;
info->fd_in = open( port, O_RDWR );
if( info->fd_in < 0 ) return -1;
info->fd_out = info->fd_in;
return 0;
}

int
openstd( portinfo_t * info )
{
info->fd_in = 0;
info->fd_out = 1;
return 0;
}

void
setupser( portinfo_t * info )
{
tcgetattr( info->fd_in, &info->in_orig );
info->in_nu = info->in_orig;
cfmakeraw( &info->in_nu );
cfsetispeed( &info->in_nu, BAUD );
cfsetospeed( &info->in_nu, BAUD );
//fixme: turn off flow control
info->in_nu.c_cflag &= ~(CRTSCTS);
tcsetattr( info->fd_in, TCSAFLUSH, &info->in_nu );
info->out_orig = info->in_orig;
info->out_nu = info->in_nu;
if( info->fd_out != info->fd_in ) {
tcgetattr( info->fd_out, &info->out_orig );
info->out_nu = info->out_orig;
cfmakeraw( &info->out_nu );
cfsetispeed( &info->out_nu, BAUD );
cfsetospeed( &info->out_nu, BAUD );
tcsetattr( info->fd_out, TCSAFLUSH, &info->out_nu );
}
}

void
setupstd( portinfo_t * info )
{
tcgetattr( info->fd_in, &info->in_orig );
info->in_nu = info->in_orig;
cfmakeraw( &info->in_nu );
tcsetattr( info->fd_in, TCSAFLUSH, &info->in_nu );
info->out_orig = info->in_orig;
info->out_nu = info->in_nu;
tcsetattr( info->fd_out, TCSAFLUSH, &info->out_nu );
}

void
teardownser( portinfo_t * info )
{
tcsetattr( info->fd_in, TCSAFLUSH, &info->in_orig );
tcsetattr( info->fd_out, TCSAFLUSH, &info->out_orig );
}

void
teardownstd( portinfo_t * info )
{
tcsetattr( info->fd_in, TCSAFLUSH, &info->in_orig );
tcsetattr( info->fd_out, TCSAFLUSH, &info->out_orig );
}

void
closestd( portinfo_t * info )
{
}

void
closeser( portinfo_t * info )
{
close( info->fd_in );
if( info->fd_out != info->fd_in ) {
close( info->fd_out );
}
info->fd_in = info->fd_out = -1;
}


int
main( int argc, char * argv[] )
{
if( argc != 2 ) {
fprintf( stderr, "usage: ser #\n" );
exit( 1 );
}
int s = atoi( argv[1] );
if( s < 0 || s > 3 ) {
fprintf( stderr, "error: port %d is not allowed\n", s );
exit( 2 );
}
char name[ 40 ];
sprintf( name, "/dev/ttyS%d", s );
portinfo_t portinfo_ser;
portinfo_t portinfo_std;
fprintf( stderr, "opening %s\n", name );
if( openser( name, &portinfo_ser ) == -1 ) {
fprintf( stderr, "error: cannot open %s\n", name );
exit( 3 );
}
fprintf( stderr, "opening tty\n" );
if( openstd( &portinfo_std ) == -1 ) {
fprintf( stderr, "error: cannot take over stdin/stdout\n" );
exit( 4 );
}
fprintf( stderr, "setting up\n" );
setupser( &portinfo_ser );
setupstd( &portinfo_std );
int n = portinfo_ser.fd_in;
if( portinfo_ser.fd_out > n ) n = portinfo_ser.fd_out;
if( portinfo_std.fd_in > n ) n = portinfo_std.fd_in;
if( portinfo_std.fd_out > n ) n = portinfo_std.fd_out;
++n;
bool isquote = false;
fprintf( stderr, "ready\n" );
while( 1 ) {
fd_set in;
FD_ZERO( &in );
FD_SET( portinfo_ser.fd_in, &in );
FD_SET( portinfo_std.fd_in, &in );
fprintf( stderr, "calling select\n" );
if( select( n, &in, 0, 0, 0 ) > 0 ) {
char c;
if( FD_ISSET( portinfo_ser.fd_in, &in ) ) {
fprintf( stderr, "reading from in\n" );
read( portinfo_ser.fd_in, &c, 1 );
fprintf( stderr, "got %d from in: " );
// always echo immediately
write( portinfo_std.fd_out, &c, 1 );
fprintf( stderr, "\n" );
}
if( FD_ISSET( portinfo_std.fd_in, &in ) ) {
fprintf( stderr, "reading keyboard\n" );
read( portinfo_std.fd_in, &c, 1 );
if( isquote ) {
if( c == 'q' ) {
break;
}
else {
char str[ 2 ];
str[ 0 ] = '~';
str[ 1 ] = c;
fprintf( stderr, "writing modem: ~ %d\n", c );
write( portinfo_ser.fd_out, str, 2 );
isquote = false;
}
}
else if( c == '~' ) {
isquote = true;
}
else {
fprintf( stderr, "writing modem: %d\n", c );
write( portinfo_ser.fd_out, &c, 1 );
}
}
}
else {
break;
}
}
teardownser( &portinfo_ser );
teardownstd( &portinfo_std );
closestd( &portinfo_std );
closeser( &portinfo_ser );
return 0;
}



Share this post


Link to post
Share on other sites
I think I'm on the right track, over the last few days I've been testing a few possible solutions. I need to know if there is any function that anyone knows of that doesn't "prompt" or wait for someone to push enter. I was thinking that each loop it would allow you to type one character into the buffer and it would take that character and add it to the end of the string. But the only commands I know(that certainly don't get the job done) are cin, scanf(), kbhit(). Im sure that there is a command that takes input but doesn't wait for it, but I can't find it in stdio.h or conio.h. Thanks.

Share this post


Link to post
Share on other sites
I don't know what you are talking about. My question is about how to recv packets while being able to accept player input. Actually to be more specific, I just currently want to know how to get input but not pause the loop for it.

Share this post


Link to post
Share on other sites
I'm very sorry hplus, I forgot to post that I couldn't get your code to work. It was rather inconiderate of me to not inform you. I do not have unix (shame on me) and I tried to convert it to win32 to no avail. I think I am on the right track, I got a tutorial on so called "asynchronous" i/o, that I have yet to read, I hope it will lead me closer to my goal. Thanks all.

Share this post


Link to post
Share on other sites

This topic is 4597 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this