C#TCP连接中的一个奇怪问题 [英] C# a strange problem in TCP connection

查看:53
本文介绍了C#TCP连接中的一个奇怪问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好!

我尝试制作一个游戏,但是有一个问题,当我尝试将每个玩家的数据发送给一个新玩家时,如果我正常启动程序,那简直就是错误的.但是,当我逐步执行代码时,它就可以工作.现在我不明白为什么.也许是因为速度?!

服务器代码:

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:

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:



PacketSender:

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:

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;




和PlayersInGame类:




And the PlayersInGame class:

public class PlayersInGame
    {
        public TcpClient client;
        public Socket client2;
        public Image img;
        public PictureBox pb;
        public string Name;
        public int weaponid, kills, xpos, ypos;
    }

推荐答案

如果您向我们展示出发生问题时捕获了什么异常....那么我们绝对可以提供帮助.....

我猜你在像客户端这样的循环骗局中徘徊...


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...


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.......
                    }
            }



问题是(我猜是..您的服务器是多线程的)

举个例子(可以模拟)

1.您从服务器和线程切换中发送"spawn"(PacketSender(pig, "spawn");)说client1,而client1同时收到"spawn",它进入case "spawn" :并在string namee = sr.ReadLine();行被阻止....

2.然后,其他某个线程将一些数据发送到client1而不是name,而client1需要一个名字...而您遇到了一个错误.

3.当client1期望一个数字(如在字符串中)并且client1将您的字符串变量解析为整数(players[index].xpos = int.Parse(sr.ReadLine());)时,sr.ReadLine()不包含数字时,可能会发生同样的事情.. bug .....

问题在发送顺序中.

另一件事,您正在发送PlayersInGame对象int 3个发送调用(意味着所有三个调用都包含相关数据,并且在服务器端必须有3个接收调用),但是您只能在一个调用中发送它……我不是说您发送像



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);


不,不是那样.....

实际上,在分布式应用程序(例如您的游戏)中,最常见的要求之一就是通过网络发送对象...而c Sharp有一个简单的解决方案:-

1.序列化对象
2.通过网络发送,
3.接收并反序列化并将其投射到所需的对象...

它将使您的代码具有防弹功能....

您还可以使用其他解决方案..
使用RPC,它将成为在您的应用程序中进行通信的最简单方法. 不要忘记投票..
好吧,如果您仍然有问题,请通过ashishtyagi40@gmail.com将您的代码发送给我,我一定会与您合作的,朋友...

最重要的是捕获您的异常并将其记录到文件中是调试多线程应用程序的关键,因此请始终将您的异常与class.function_name,line_no和time_stamp一起记录

:cool:


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:


当代码仅在调试时起作用时,几乎可以确定您具有 ^ ].竞态条件的一种可能是在您的生成"代码中:当您调用ReadLine时,服务器端可能会或可能不会完成名称和坐标的编写.根据两次调用的时间(生成的ReadLine和服务器的WriteLine),您的代码将起作用或失败.
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.


这篇关于C#TCP连接中的一个奇怪问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆