C#服务端开发入门题

本文介绍了两个C#编程题目:一是实现一个基础的服务端,能够接收客户端请求,解析JSON字符串并调用相应的方法;二是利用C#读取Excel文件数据并插入到数据库中,通过创建model类和特性实现列名到字段的转换。这两个练习涵盖了C#的基础语法、网络编程以及数据操作。
摘要由CSDN通过智能技术生成

总结

#通过下面两小题熟悉c#的基础语法,还有c#网络编程。作为c#游戏服务端开发入门的两道基础习题。


一、实现一个简单的服务端,要求能解析请求的字符串,并根据字符串里的服务名和接口名调用到对应的实际方法,并传入字符串中包含的参数

请求字符串示例:
{“parameter1”: 1234, “parameter2”: “daqing”, “cmd”: “TestService.Enter”}

1.Program.cs类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace post
{
    class Program
    {
        static void Main(string[] args)
        {
            ServerControl server = new ServerControl();
            server.start();
            Console.ReadKey();
        }
    }
}

2.ServerControl.cs类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace post
{
    public class ServerControl
    {
        private Socket serverSocket;
        private List<Socket> clientList;

        public ServerControl()
        {
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建服务器端socket  ipv4, 流式传输,  tcp协议
            clientList = new List<Socket>();
        }

        public void start()
        {
            serverSocket.Bind(new IPEndPoint(IPAddress.Any, 8080)); //绑定IP 及 端口 IPAddress.Any 表示程序运行在的机器IP地址    
            serverSocket.Listen(10);// 监听 端口上 客户端的连接,排队等待连接的最大数量
            Console.WriteLine("服务器启动成功");

            Thread threadAccept = new Thread(accept);//创建一个接受客户端连接的线程   该线程机制可以接受多个客户端连接
            threadAccept.IsBackground = true;//后台执行
            threadAccept.Start();//启动线程
        }

        private void accept()
        {
            while (true)
            {
                //接受客户端连接,并返回socket, 该方法会阻塞挂起当前线程
                Socket client = serverSocket.Accept();
                IPEndPoint point = client.RemoteEndPoint as IPEndPoint; //远程连接过来IP 指客户端IP
                Console.WriteLine(point.Address + "[" + point.Port + "]" + "连接成功");
                clientList.Add(client);

                Thread thradReceive = new Thread(receive);//开启一个新线程用于接收数据
                thradReceive.IsBackground = true;
                thradReceive.Start(client);
                //Console.WriteLine("服务器启动成功");
            }
        }

        public  void GetAndExecuteMethod(string className, string methodName, object[] parameters)
        {
            try
            {
                //命名空间.类
                Type type = Type.GetType("post." + className);
                if (type == null)
                    throw new NullReferenceException("类" + className + "不存在");
                    
                Object obj = Activator.CreateInstance(type);                
                MethodInfo[] info = type.GetMethods();
                for (int i = 0; i < info.Length; i++)
                {
                    var md = info[i];
                    string mothodName = md.Name;
                    //方法名相同且参数个数一样
                    if (mothodName == methodName)
                    {                        
                        md.Invoke(obj,parameters);
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        private void receive(Object obj)
        {
            while (true)
            {
                Socket client = obj as Socket;
                IPEndPoint point = client.RemoteEndPoint as IPEndPoint;
                try
                {
                    byte[] msg = new byte[1024];//申请一块字节数组用于存放接收的数据
                    int msgLen = client.Receive(msg);//接收字节数组  返回接收的长度     该函数会阻塞所在的线程 所以放到新线程中
                    string msgStr =  Encoding.UTF8.GetString(msg, 0, msgLen); //转换字节数组成字符串 并输出
                    Parameter rb = JsonConvert.DeserializeObject<Parameter>(msgStr);
                    //ParameterTest rbTest = JsonConvert.DeserializeObject<ParameterTest>(msgStr);
                    string[] s = (rb.cmd).Split('.');                   
                    object[] parameters = new object[] {rb};
                    //将类名的字符串及方法名的字符串传递过去
                    GetAndExecuteMethod(s[0], s[1],parameters);                                 
                    //服务器返回响应
                    broadcast(client, msgStr);
                    break;
                }
                catch
                {
                    Console.WriteLine(point.Address + "[" + point.Port + "]" + "积极断开");
                    clientList.Remove(client);
                    break;
                }
            }
        }

        private void broadcast(Socket clientOther, string msg)
        {
            foreach (var client in clientList)
            {
                if (client == clientOther)
                {
                    //TestService testservice = new TestService();                   
                    //Console.WriteLine("服务器返回响应");
                    //client.Send(Encoding.UTF8.GetBytes(msg+"收到后,"));
                }
                else
                {
                    client.Send(Encoding.UTF8.GetBytes(msg));
                }
            }
        }
    }
}

3.Parameter.cs类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace post
{
    class Parameter
    {
        public int parameter1 { get; set; }

        //public int parameter2 { get; set; }
        public string parameter2 { get;set; }

        public string cmd { get; set; }
    }
}

4.TestService.cs类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace post
{
    class TestService
    {
        public void Enter(int parameter1,string parameter2)
        {
            Console.WriteLine("调用TestService类的Enter方法,输出参数的值");          
            Console.WriteLine("parameter1:{0}",parameter1);
            Console.WriteLine("parameter2:{0}",parameter2);            
        } 
    }
}

二、2. 实现一个程序,可以读取一份Excel文档里的数据,并将其写入到对应的数据库表,要求使用创建model类和特性来实现Excel中文列名到数据库表字段的通用转换。

示例表:

CREATE TABLE [dbo].[user-info](
[Id] [int] NOT NULL,
[UserName] varchar NOT NULL,
[Gold] [int] NOT NULL,
[Silver] [bigint] NOT NULL,
PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

1.Program.cs类

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.Data.SqlClient;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace lianjieTest
{
    class Program
    {
        static void Main(string[] args)
        {
            connection();
            Console.ReadKey();
        }

        public static int connection()
        {
            //数据库连接串
            string connStr = "Data source=.;Initial Catalog=test;Trusted_Connection=SSPI";
            SqlConnection sql = new SqlConnection(connStr);

            try
            {
                sql.Open();
                DataSet ds = ExcelToDataSet("D:\\wanjiaxinxibiao.xlsx");
                
                for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
                {
                    
                    List<object> list = new List<object>();
                    List<object> list1 = new List<object>();
                    model p = new model();
                    Type t = p.GetType();
                    foreach (PropertyInfo pi in t.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
                    {
                        object[] Attribute = pi.GetCustomAttributes(false);
                        MarkAttribute myTest = Attribute[0] as MarkAttribute;
                        //将遍历类属性,根据model类属性去读取相应的excel表格
                        object v = Convert.ChangeType(ds.Tables[0].Rows[i][myTest.FiledName].ToString(), t.GetProperty(pi.Name).PropertyType);
                        t.GetProperty(pi.Name).SetValue(p, v, null);                       
                                             
                        list.Add(pi.Name);
                        list1.Add(Convert.ToString(t.GetProperty(pi.Name).GetValue(p, null)));
                    }
                    //将每个属性的值拼接成sql操作操作语句
                    string str1 = "insert into [user-info] (";
                    string str2 = string.Join(",",list.ToArray());
                    string str3 = ") values('"+string.Join("','", list1.ToArray());
                    string str4 = "')";
                    string str = str1 + str2 + str3 + str4;                  
                    //执行sql命令插入
                    SqlCommand command = new SqlCommand(str, sql);
                    command.ExecuteNonQuery();
                }
                Console.WriteLine("导入数据库成功");
            }
            catch (Exception ex)
            {
                Console.WriteLine("导入数据库失败");
                throw ex;
            }
            finally
            {
                if (sql != null)
                {
                    //关闭数据库连接
                    sql.Close();
                }
            }
            return 0;
        }

        public static DataSet ExcelToDataSet(string filename)
        {

            string strCon = "Provider=Microsoft.Jet.OLEDB.4.0;" +

                            "Extended Properties=Excel 8.0;" +

                            "data source=" + filename;

            OleDbConnection myConn = new OleDbConnection(strCon);
            //"玩家信息"为表单标签页名 
            string strCom = " SELECT * FROM [玩家信息$]";
            myConn.Open();

            OleDbDataAdapter myCommand = new OleDbDataAdapter(strCom, myConn);
            DataSet ds;
            ds = new DataSet();
            myCommand.Fill(ds, "玩家信息");
            myConn.Close();
            return ds;
        }
    }
}

2.MarkAttribute.cs类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace lianjieTest
{
    [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
    class MarkAttribute : Attribute
    {
        public MarkAttribute(string markname)
        {
            this.FiledName = markname;
        }

        public string FiledName
        {
            get;
            set;
        }
    }
}

3.model.cs类

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace lianjieTest
{
    class model
    {
        [Mark("玩家编号")]
        public int Id { get; set; }

        [Mark("玩家昵称")]
        public string UserName { get; set; }

        [Mark("元宝数量")]
        public int Gold { get; set; }

        [Mark("银两数量")]
        public long Silver { get; set; }      
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值