Click here to Skip to main content
15,896,727 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello!

I try to make a game, but there's a problem, when I try to send each player's data to one new player, it simply goes wrong, if I start the progream normally. But when I go through the code step-by-step, it works. Now I just can't understand why. Maybe because of the speed?!

Server code:
C#
static void SpawnAll(PlayersInGame pig)
        {
            //all players data to one player
            for (int i = 0; i < players.Count; i++)
            {
                if (players[i].xpos != pig.xpos)
                {
                    PacketSender(pig, "spawn");
                    PacketSender(pig, players[i].Name);
                    PacketSender(pig, players[i].xpos);
                    PacketSender(pig, players[i].ypos);
                }
            }
        }


PacketSender:
C#
static void PacketSender(PlayersInGame pig, object data)
        {
            if (pig.client.Connected)
            {
                StreamWriter sw = new StreamWriter(pig.client.GetStream());
                sw.WriteLine(data);
                sw.Flush();
            }
            else
                players.Remove(pig);
        }




Client code:
C#
case "spawn":
                        string namee = sr.ReadLine();
                        int index = GetIndexByName(namee);
                        players[index].xpos = int.Parse(sr.ReadLine());
                        players[index].ypos = int.Parse(sr.ReadLine());
                        players[index].pb = new PictureBox();
                        players[index].pb.Location = new Point(players[index].xpos, players[index].ypos);
                        players[index].pb.SizeMode = PictureBoxSizeMode.StretchImage;
                        players[index].pb.Size = new Size(50, 50);
                        players[index].pb.Image = players[index].img;
                        BeginInvoke((MethodInvoker)delegate { Controls.Add(players[index].pb); });
                        break;



And the PlayersInGame class:
MIDL
public class PlayersInGame
    {
        public TcpClient client;
        public Socket client2;
        public Image img;
        public PictureBox pb;
        public string Name;
        public int weaponid, kills, xpos, ypos;
    }
Posted
Updated 15-Jan-11 22:42pm
v3
Comments
Richard MacCutchan 16-Jan-11 7:47am    
Saying "it simply goes wrong" is of no help to anyone. Please explain exactly what results you get and what you expect to get, so people have a clue what to look for.
velvet7 16-Jan-11 8:04am    
It doesn't "spawn" the picturebox. But in step-by-step mode it works.

if you show us that what exception was caught when something goes wrong.... then we can help definitely.....

I guess your are havig a loop con client side like...


C#
ASCIIEncoding encoder = new ASCIIEncoding();
            int bytesRead = 0;
            byte[] receiveBuffer = new byte[1000];
            string data;
            while (true)
            {
                try
                    {
                        bytesRead = cl.GetStream().Read(receiveBuffer, 0, nBuff);
                        data = encoder.GetString(receiveBuffer, 0, bytesRead);
                        switch(data)
                        {
                            // some code...
                            case "spawn":
                            string namee = sr.ReadLine();
                            int index = GetIndexByName(namee);
                            players[index].xpos = int.Parse(sr.ReadLine());
                            players[index].ypos = int.Parse(sr.ReadLine());
                            players[index].pb = new PictureBox();
                            players[index].pb.Location = new Point(players[index].xpos, players[index].ypos);
                            players[index].pb.SizeMode = PictureBoxSizeMode.StretchImage;
                            players[index].pb.Size = new Size(50, 50);
                            players[index].pb.Image = players[index].img;
                            BeginInvoke((MethodInvoker)delegate { Controls.Add(players[index].pb); });
                            break;
                            // some code.....
                        }
                    }
                    catch (Exception ex)
                    {
                        // some code.......
                    }
            }


And the problem is (as i guess.. your server is multi-threaded)

Take a case (can be simulated)

1. You send "spawn" (PacketSender(pig, "spawn");) to say client1 from server and thread switched and same time client1 received "spawn" and it goes to the case "spawn" : and blocked on string namee = sr.ReadLine(); line....

2. Then some other thread send some data to client1 which is not a name while client1 expecting a name... and you got a bug.

3. May be same thing happened on when client1 expecting a number(as in string) and client1 parse your string variable to integer (players[index].xpos = int.Parse(sr.ReadLine());) where sr.ReadLine() not containing a number.... bug.....

problem is in sending sequence..

Another thing, you are sending PlayersInGame object int 3 send calls (means all three call contain related data and there must be 3 receive calls in server side ), but you can send it in only in one call... I am not saying you send like
PacketSender(pig, players[i].Name + players[i].pos + players[i].pos);

No not like that.....

Actually one of the most common requirement in distributed application (like your game) is sending objects across network... And c sharp have a simple solutions:--

1. serialize your object
2. Send it on network,
3. Receive it and deserialize and cast it to your desired object...

It will make your code bullet-proof....

You can also use another solution..
use RPC it will make an easiest way to communicate in your application..
Don't forget voting..
well if you still having problem send me your code at ashishtyagi40@gmail.com, and i will definitely cooperate you friend...

Most important thing catch your exception and log it into a file is the key to debug a multi-threaded application, so always log your exception along with class.function_name, line_no and time_stamp

:cool:
 
Share this answer
 
v4
Comments
Manfred Rudolf Bihy 16-Jan-11 9:24am    
Good detailed answer! 5+
Ashish Tyagi 40 16-Jan-11 10:53am    
But there is no vote Manfred... give me a 5 please
velvet7 16-Jan-11 9:33am    
"if you show us that what exception was caught when something goes wrong.... then we can help definitely....."
It doesn't even throw exception.
When the code works only when you debug it, it's nearly certain that you have a race condition[^]. One possibility of race condition is in your "spawn" code: when you call ReadLine, the server side may or may not have finished writing the name and the coordinates. Depending on the timing of the two calls (spawn's ReadLine and server's WriteLine) your code will either work or fail.
 
Share this answer
 
Comments
Manfred Rudolf Bihy 16-Jan-11 9:24am    
5+ Good call!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900