例外:客户C#

时间:2016-08-26 04:11:21

标签: c# python networking visual-studio-2015

我正在尝试通过试验和错误来学习C#。我有一个Python服务器,C#中的客户端。

客户端应该从服务器获取数据,将其保存到磁盘((它没有)),然后继续使用该数据进行通信,直到用户决定退出它为止。

不幸的是,它已经引发了异常访问冲突很长一段时间,并没有提供有关原因的有用信息。

代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Scripting.Hosting;
using System.Threading;
using Rage;
using System.Net.Sockets;
using System.IO;

[assembly: Rage.Attributes.Plugin("LSPDFROnlineClient", Description = "LSPDFR Online Client. Used to connect to LSPDFR Online.", Author = "Thecheater887")]

namespace LSPDFROnlineClient
{

    public class EntryPoint
    {
        private static int IsDead;

        public static void Main()
        {
            IsDead = 0;
            Thread mt = new Thread(new ThreadStart(Run));
            mt.Start();
            while (true)
            {
                if (IsDead == 1)
                {
                    break;
                }
                GameFiber.Yield();
            }
            return;
        }
        public static void Run()
        {
            File.WriteAllText("C:/ProgramData/dbg.log","1");
            try
            {
                Byte[] header;
                Byte[] packet;
                Byte[] data;
                Byte[] kad;
                Byte[] td;
                int paylen;
                String rd;
                String nd;
                String msgid;

                File.WriteAllText("C:/ProgramData/dbg.log", "2");

                TcpClient connector = new TcpClient();
                connector.Connect("127.0.0.1", 5773);
                NetworkStream conn = connector.GetStream();
                try {
                    File.WriteAllText("C:/ProgramData/dbg.log", "3");
                    FileStream savedat = File.OpenRead("C:/Users/Public/Documents/save.dat");
                    BinaryReader savdat = new BinaryReader(savedat);
                    nd = savdat.ReadString();
                    savdat.Close();
                    if (nd.Length == 16)
                    {

                    } else {
                        File.WriteAllText("C:/ProgramData/save.dat", "user000000000000");
                        nd = "user000000000000";
                    }
                }
                catch
                {
                    File.WriteAllText("C:/ProgramData/save.dat", "user000000000000");
                    nd = "user000000000000";
                }
                File.WriteAllText("C:/ProgramData/dbg.log", "4");
                data = new Byte[26];
                data = Encoding.ASCII.GetBytes("clogr00000" + nd);
                conn.Write(data, 0, data.Length);

                while (true)
                {
                    try
                    {
                        // Get header of packet
                        header = new Byte[26];
                        Int32 rcvhead = conn.Read(header, 0, header.Length);
                        String hd = Encoding.ASCII.GetString(header, 0, rcvhead);
                        //Deal with it 8-)
                        msgid = hd.Substring(0, 5);
                        paylen = Convert.ToInt32(hd.Substring(5, 5));
                        string servkey = hd.Substring(10, 16);
                    }
                    catch
                    {
                        continue;
                    }
                    File.WriteAllText("C:/ProgramData/dbg.log", "5");
                    try
                    {
                        //Receive packet data
                        if (paylen > 0)
                        {
                            packet = new Byte[paylen];
                            Int32 newdata = conn.Read(packet, 0, packet.Length);
                            rd = Encoding.ASCII.GetString(packet, 0, newdata);
                        }
                        else
                        {
                            rd = null;
                        }
                        File.WriteAllText("C:/ProgramData/dbg.log", "6");
                        if (msgid == "ConOK")
                        {
                            File.WriteAllText("C:/ProgramData/dbg.log", "7");
                            string userid = rd.Substring(0, 16);
                            Game.DisplayHelp(rd.Substring(16, (rd.Length - 16)));
                            File.WriteAllText("C:/ProgramData/save.dat", userid);
                            File.WriteAllText("C:/ProgramData/dbg.log", "8");
                        }
                        else if (msgid == "savdt")
                        {
                            File.WriteAllText("C:/ProgramData/dbg.log", "9");
                            string[] tnd = rd.Split(',');
                            var nud = new List<string>();
                            nud.Add("Player1");
                            nud.AddRange(tnd);
                            File.WriteAllText("C:/ProgramData/dbg.log", "A");
                            string name = nud[0];
                            string streetname = nud[1];
                            int money = Convert.ToInt32(nud[2]);
                            int bounty = Convert.ToInt32(nud[3]);
                            int playerrep = Convert.ToInt32(nud[4]);
                            File.WriteAllText("C:/ProgramData/dbg.log", "B");
                            int rep = Convert.ToInt32(nud[5]);
                            string pclass = nud[6];
                            bool canbecop = Convert.ToBoolean(nud[7]);
                            int rank = Convert.ToInt32(nud[8]);
                            int stars = Convert.ToInt32(nud[9]);
                            int cites = Convert.ToInt32(nud[10]);
                            File.WriteAllText("C:/ProgramData/dbg.log", "C");
                            int citesgiven = Convert.ToInt32(nud[11]);
                            int citesdismissed = Convert.ToInt32(nud[12]);
                            int arrestsmade = Convert.ToInt32(nud[13]);
                            int arrested = Convert.ToInt32(nud[14]);
                            int convictionsmade = Convert.ToInt32(nud[15]);
                            int convitced = Convert.ToInt32(nud[16]);
                            string warrant = nud[17];
                            File.WriteAllText("C:/ProgramData/dbg.log", "D");
                            int prisontimeremaining = Convert.ToInt32(nud[18]);
                            int copskilled = Convert.ToInt32(nud[19]);
                            int crimskilled = Convert.ToInt32(nud[20]);
                            int civskilled = Convert.ToInt32(nud[21]);
                            int bountyclaimed = Convert.ToInt32(nud[22]);
                            int overflowprep = Convert.ToInt32(nud[23]);
                            string title = nud[24];
                            bool banned = Convert.ToBoolean(nud[25]);
                            bool vip = Convert.ToBoolean(nud[26]);
                            int viprank = Convert.ToInt32(nud[27]);
                            File.WriteAllText("C:/ProgramData/dbg.log", "E");

                            var v3 = new Vector3();
                            float posx = Convert.ToSingle(nud[29]);
                            float posy = Convert.ToSingle(nud[30]);
                            float posz = Convert.ToSingle(nud[31]);
                            v3.X = posx;
                            v3.Y = posy;
                            v3.Z = posz;

                            File.WriteAllText("C:/ProgramData/dbg.log", "EE");
                            int rot = Convert.ToInt32(nud[32]);
                            File.WriteAllText("C:/ProgramData/dbg.log", "FF");

                            World.TeleportLocalPlayer(v3, false);
                            File.WriteAllText("C:/ProgramData/dbg.log", "F");
                            string custommessage = nud[28];
                            if (custommessage == "null")
                            {

                            } else {
                                Game.DisplayNotification(custommessage);
                            }
                        }
                        else if (msgid == "isalv")
                        {
                            kad = new Byte[26];
                            kad = Encoding.ASCII.GetBytes("yesil00000" + nd);
                            conn.Write(kad, 0, kad.Length);
                        }
                        else if (msgid == "pospk")
                        {

                        }
                        else
                        {
                            Game.DisplayNotification("Unknown packet recieved! ID: " + msgid);
                        }
                        //send end client turn
                        td = new Byte[26];
                        td = Encoding.ASCII.GetBytes("endmt00000" + nd);
                        conn.Write(td, 0,td.Length);
                        File.WriteAllText("C:/ProgramData/dbg.log", "0");
                        //
                    }
                    catch (Exception e)
                    {
                        Game.DisplayHelp(Convert.ToString(e));
                        Game.DisplayNotification("LSPDFR Online has crashed. Try reloading it maybe..?");
                    }
                }
            } catch (Exception e) {
                Game.DisplayHelp(Convert.ToString(e));
                Game.DisplayNotification("Connection interrupted! Reconnecting....");
                IsDead = 1;
                return;
            }
        }
    }
}

协议就是这样;

Client -> Server: LoginRequest
Server -> Client: LoginOkay
Client -> Server: EndTurnMessage
Server -> Client: SaveDataMessage
Client -> Server: EndTurnMessage
Server -> Client: PositionUpdatePacket
Client -> Server: EndTurnMessage

然后继续例程,但是,服务器只接收这些EndTurnMessage个数据包中的一个,这意味着它在保存数据部分上窒息,对吗?

可能,但那是在没有缺陷的早期工作,并且从那时起就没有被修改过。

这是一个类文件,因此无法进行调试,而且我一直在撕扯我的头发是什么原因造成的。

是的,它是垃圾代码,需要在某些时候重写,我知道,但是在我完全重写之前我还是喜欢它。

TL; DR:为什么此代码会引发访问冲突?它位于savdt部门或之后。

更新:我修复了第一个答案中发布的问题,然而,这并没有做太多,所以,正如答案和评论中所发表的那样,它是相当的很难用程序调试,所以我会尝试每一行代码的旧式日志信息路径。我会保持更新。

更新2:我从日志调试中发现导致错误的行是World.TeleportLocalPlayer(v3, false);。不幸的是,World无法继承,文档声称Vector3要求您使用get和set设置其内部值。我之前在MSDN上看到过,但不知道如何搜索它,并且该get对象中还有setVector3方法可用。

2 个答案:

答案 0 :(得分:1)

您可能有一个保持打开的流,这会阻止创建一个新流。如果msgid是“ConOK”,那么在写操作完成后,您将创建一个新实例而不关闭它。

if (msgid == "ConOK"){
    string userid = rd.Substring(0, 16);
    Game.DisplayHelp(rd.Substring(16, (rd.Length - 16)));
    FileStream savedat = File.OpenWrite(("C:/ProgramData/save.dat"));
    BinaryWriter savdat = new BinaryWriter(savedat);
    savdat.Write(userid);
    // Close file stream here
 }

但这只是第一次猜测。您可以通过使用调试器来帮助我们和您自己。您的代码包含在“类文件”中的事实不是问题,而是一个要求。

Hava看看这篇文章,了解有关在C#世界中进行调试的更多信息: http://www.dotnetperls.com/debugging

答案 1 :(得分:1)

乍一看,你可以有不同类别的错误。忽略程序的逻辑流程和预期行为,让我们从基本调试开始。

  • 在这一步,不要使用线程和光纤,从Main只需调用Run

  • 没有强大的输入验证

  • 使用更多的try catch,隔离一小段代码

  • catch中的
  • ,打印ex.Message和ex.StackTrace

  • 仔细阅读有关您所调用方法的文档及其可能的例外情况

  • 你在异常(catch)中写一个文件很奇怪

  • 全局变量的可能竞争条件? 在Run中设置IsDead使用Interlocked.Increment https://msdn.microsoft.com/en-us/library/dd78zt0c(v=vs.110).aspx

...

  • 删除未使用的(我觉得像Microsoft.Scripting.Hosting),它只会混淆一只猫