Thread: Socket (SOCK_STREAM) Connection and reread

  1. #1
    Registered User
    Join Date
    Mar 2011
    Posts
    21

    Angry Socket (SOCK_STREAM) Connection and reread

    I'm writing a pretty trivial game server, and am having some trouble with my sockets and the dataflow therein. I have in my server the following code:
    Code:
    for(i=0;;i= (i+1)%2){
    	send(p[i], board, boardsize, 0);
    	recv(p[i], move, movesize, 0);
    	if (!validate(move)){
    		i--;
    		continue;
    	}
    	if (!apply(move))
    		break;
    	if (victory())
    		break;
    	send(p[i], board, boardsize, 0);
    }
    Where "p" is an int[2] holding my socket fds, "board" is a global char[5] holding a null-terminated board description, "move" is a char[3] holding a null terminated move description.
    validate(move) returns a boolean (read: int) on the validity of the move.
    apply(move) applies the move, returning one on success and zero on failure or resignation.
    victory() checks for the victory condition on the board.

    I'll include the pertinent client loop below, but I'm pretty sure the problem is in my server. When I run it on my little 32 bit system, it seems to run just fine, but when I port it to the 64bit systems it's actually going to be run on, the server has the very, VERY strange habit of passing back the board to the player unedited, then cycling around on the loop and passing the correct board to the other player. I, for the life me, can't figure out why. Any ideas?

    In the client:
    Code:
    while(1){
    	for(i=0;i<5;i++)
    		oldboard[i]=newboard[i];
    	while(1){
    		printf("Your move? ");
    		fgets(buf, bufLen, stdin);
    		buf[strlen(buf)-1]=0;
    		if (strlen(buf)==3 && buf[1]==' '){
    			move[0]=buf[0]-'0';
    			move[1]=buf[2]-'0';
    			if (valid(move, newboard)) break;
    		}
    		printf("\n\"%s\" is not a valid move.\n\n", buf);
    	}
    	send(sock, move, 3, 0);
    	if (boardsize>recv(sock, newboard, boardsize, 0))fail("Server down.\nTry again later");
    	check(newboard);
    	
    	if (eq(oldboard, newboard)){
    		pboard(newboard);
    		printf("Server Rejected Move\n");
    		continue;
    	}
    	pboard(newboard);
    	printf("Waiting on %s..\n", opphandle);
    	if (1>recv(sock, newboard, boardsize, 0))fail("Server down.\nTry again later");
    	check(newboard);
    	printf("After %s's move:\n", opphandle);
    	pboard(newboard);	
    }
    where oldboard and newboard are local char[5] holding null-terminated board descriptions, move is as before.
    eq(oldboard, newboard) checks to see if the boards are the same.
    pboard(board) prints the board.
    check(board) checks to see if the board secretly contains a state message concerning the program (Win conditions, Lose conditions, Server Errors, etc.)

    The client has already received a starting board before starting the loop.

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Since you mention states, why isn't the client just looking at its current state to see what to expect/send? The whole thing should just be state based, for the client and the server.


    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    Mar 2011
    Posts
    21
    It less uses states as it does co-opt the fact that the board is represented as a char[5] to send easily identifiable messages. "Win.", "Lose", "Err.", etc, which the client recognizes and has responses to. Yes, I /could/ re-write the whole program, but I'm not wiling to throw away the thought that it should work this way (as it does on my 32 bit system). Do you have any idea why it doesn't?

  4. #4
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    You really ought to be checking the return value of your send and recv calls and make sure all the data is getting sent properly. If not, you need to print descriptive error messages, perhaps including how many bytes did/didn't get sent, and what the error code and message are (errno/strerror or perror). For that matter, you should be checking pretty much all library calls.

  5. #5
    Registered User
    Join Date
    Mar 2011
    Posts
    21
    Thanks, anduril, I ought have been checking my returns. Or, moreover, just been using good coding practices in general.

    Turns out, earlier in my code for the client I had sent a string I declared to be 21 characters long, when it was in fact of variable length. This confused the holy hell out of my server, apparently trying to find 21 characters of sent data, such that when I tried to grab my move descriptors, it was still trying to figure out what I had meant before, and throwing off the way the loops were intended to mesh. Stupid monkey.

    Thanks for your help, guys.

Popular pages Recent additions subscribe to a feed

Tags for this Thread