`
lindexi-gd
  • 浏览: 139765 次
社区版块
存档分类
最新评论

wpf C# 数据库 c/s 个人信息管理 wpf局域网通信

 
阅读更多

系统功能基本要求

  • 通讯录信息
    -通讯人姓名
    -联系方式
    -工作地点
    -城市
    -备注
  • 备忘录信息
    -包括什么时间
    -事件
    -地点
  • 日记信息
    -时间
    -地点
    -事情
    -人物
    -个人财物管理
    -总收入
    -消费项目
    -消费金额
    -消费时间
    -剩余资金

wpf局域网通信

wpf局域网聊天

想到做一个c/s,传输我就想到了json
json需要先安装nuget中Newtonsoft.Json;
nuget
安装
因为要找比较多,可以搜索
安装
然后在文件写using Newtonsoft.Json;

把类转json

JsonConvert.SerializeObject(obj)

把json转类

        private T Deserialize<T>(string str)
        {
            try
            {
                T temp = JsonConvert.DeserializeObject<T>(str);
                return temp;
            }
            catch (JsonException e)
            {
                reminder = "输入不是ObservableCollection<T> json" + e.Message;
            }
            return default(T);
        }

参考很多博客写出了局域网传输的代码

服务器:

    public class principal_Computer
    {
        public principal_Computer(System.Action<string> ReceiveAction)
        {
            this.ReceiveAction = ReceiveAction;

            ServerSocket = new Socket(AddressFamily.InterNetwork , SocketType.Stream , ProtocolType.Tcp);
            IPAddress ip = IPAddress.Any;
            ServerInfo = new IPEndPoint(ip , port);
            ServerSocket.Bind(ServerInfo);//将SOCKET接口和IP端口绑定
            ServerSocket.Listen(10);//开始监听,并且挂起数为10

            ClientSocket = new Socket[65535];//为客户端提供连接个数         
            ClientNumb = 0;//数量从0开始统计

            ServerThread = new Thread(new ThreadStart(RecieveAccept));//将接受客户端连接的方法委托给线程
            ServerThread.Start();//线程开始运行
        }

        public void send(string str)
        {
            byte[] MsgBuffer = encoding.GetBytes(str);
            for (int i = 0; i < ClientNumb; i++)
            {
                if (ClientSocket[i].Connected)
                {
                    //回发数据到客户端
                    ClientSocket[i].Send(MsgBuffer , 0 , MsgBuffer.Length , SocketFlags.None);
                }
            }
        }

        //接受客户端连接的方法
        private void RecieveAccept()
        {
            while (true)
            {
                //Accept 以同步方式从侦听套接字的连接请求队列中提取第一个挂起的连接请求,然后创建并返回新的 Socket。
                //在阻止模式中,Accept 将一直处于阻止状态,直到传入的连接尝试排入队列。连接被接受后,原来的 Socket 继续将传入的连接请求排入队列,直到您关闭它。
                byte[] buffer = new byte[65535];
                ClientSocket[ClientNumb] = ServerSocket.Accept();
                ClientSocket[ClientNumb].BeginReceive(buffer , 0 , buffer.Length , SocketFlags.None ,
                new AsyncCallback(RecieveCallBack) , ClientSocket[ClientNumb]); 
                ReceiveAction(encoding.GetString(buffer));
                ClientNumb++;
            }
        }

        //回发数据给客户端
        private void RecieveCallBack(IAsyncResult AR)
        {
            try
            {
                Socket RSocket = (Socket)AR.AsyncState;               
                    byte[] MsgBuffer = new byte[65535];
                    //同时接收客户端回发的数据,用于回发
                    RSocket.BeginReceive(MsgBuffer , 0 , MsgBuffer.Length , SocketFlags.None , ar =>
                    {                        
                        try
                        {
                            RSocket.EndReceive(ar);
                            ReceiveAction(encoding.GetString(MsgBuffer).Trim('\0' , ' '));
                            RecieveCallBack(ar);
                        }
                        catch (SocketException e)
                        {
                            ReceiveAction("对方断开连接" + e.Message);
                        }

                    } , RSocket);

            }
            catch
            {
            }

        }

        private IPEndPoint ServerInfo;//存放服务器的IP和端口信息
        private Socket ServerSocket;//服务端运行的SOCKET
        private Thread ServerThread;//服务端运行的线程
        private Socket[] ClientSocket;//为客户端建立的SOCKET连接
        private int ClientNumb;//存放客户端数量
        //private byte[] MsgBuffer;//存放消息数据
        private int port = 54321; //端口号
        private System.Action<string> ReceiveAction;
        private Encoding encoding = Encoding.Default;

    }

客户端

    public class slaveComputer
    {
        public slaveComputer(System.Action<string> ReceiveAction)
        {
            this.ReceiveAction = ReceiveAction;
            //定义一个IPV4,TCP模式的Socket
            ClientSocket = new Socket(AddressFamily.InterNetwork , SocketType.Stream , ProtocolType.Tcp);   
        }
        public void access(string ip)
        {
            ServerInfo = new IPEndPoint(IPAddress.Parse(ip) , port);
            //客户端连接服务端指定IP端口,Sockket
            ClientSocket.Connect(ServerInfo);
            //将用户登录信息发送至服务器,由此可以让其他客户端获知
            ClientSocket.Send(encoding.GetBytes(" 进入系统!\n"));
            //开始从连接的Socket异步读取数据。接收来自服务器,其他客户端转发来的信息
            //AsyncCallback引用在异步操作完成时调用的回调方法         
            ReceiveCallBack(ReceiveAction);
        }

        public void send(string str)
        {
           byte[] buffer = encoding.GetBytes(str);            
            ClientSocket.Send(buffer , 0 , buffer.Length , SocketFlags.None);
        }
        private IPEndPoint ServerInfo;
        private Socket ClientSocket;       
        private Encoding encoding = Encoding.Default;
        private System.Action<string> ReceiveAction;
        private void ReceiveCallBack(System.Action<string> ReceiveAction)
        {
            try
            {
                //结束挂起的异步读取,返回接收到的字节数。 AR,它存储此异步操作的状态信息以及所有用户定义数据                
                byte[] MsgBuffer = new byte[65535];
                ClientSocket.BeginReceive(MsgBuffer , 0 , MsgBuffer.Length , SocketFlags.None , ar =>
                {
                    //对方断开连接时, 这里抛出Socket Exception
                    //An existing connection was forcibly closed by the remote host 
                    try
                    {

                        ClientSocket.EndReceive(ar);
                        ReceiveAction(encoding.GetString(MsgBuffer).Trim('\0' , ' '));
                        ReceiveCallBack(ReceiveAction);
                    }
                    catch (SocketException e)
                    {
                        ReceiveAction("对方断开连接" + e.Message);
                    }

                } /*new AsyncCallback(ReceiveCallBack)*/ , null);

            }
            catch
            {

            }
        }
        private int port = 54321; //端口号

    }

使用方法是
写出一个private System.Action<string> ReceiveAction;

初始化

            ReceiveAction = str =>
            {
                //因为接受使用byte[] 会有很多空的字符,去掉就是消息
                string temp= str.Trim('\0' , ' ');
                if (!string.IsNullOrEmpty(temp))
                {
                    //reminder是提示的字符串
                    reminder = temp;
                }
            };

使用服务器

 var _principal_Computer = new principal_Computer(ReceiveAction);

使用客户端

            var _slaveComputer = new slaveComputer(ReceiveAction);            
            _slaveComputer.access(ip);

客户端和服务器发送都是使用send
而服务器有多个客户端,发送可以指明发送到哪个客户端,可以全发送。

发送信息时,对信息进行一个类转json

因为发送信息不知道需要做什么,于是做了一个枚举,一个类

 /// <summary>
    /// 发送消息
    /// </summary>
    public class ctransmitter
    {
        public ctransmitter(int id , ecommand command , string str/*,int ran*/)
        {
            this.id = id.ToString();
            this.command = command.ToString();
            this.str = str;
            //this.ran = ran.ToString();
        }

        public string id
        {
            set;
            get;
        }
        public string command
        {
            set;
            get;
        }
        public string str
        {
            set;
            get;
        }
        //public string ran
        //{
        //    set;
        //    get;
        //}
        public override string ToString()
        {
            return JsonConvert.SerializeObject(this);
        }
    }

    public enum ecommand
    {
        login,//登录
        id,//分配id      
        faddressBook,//通讯录
        ce
    }

ctransmitter里面ToString把这个类转换为json,之后接收就把json转换为类,然后根据command来得到发送的命令

                ctransmitter transmitter = JsonConvert.DeserializeObject<ctransmitter>(json);
                ecommand command = (ecommand)Enum.Parse(typeof(ecommand) , transmitter.command);
                switch (command)
                {
                    case ecommand.ce:
                        reminder("收到" + transmitter.id);
                        break;
                }

客户端循环等待服务器发送的消息,收到就把信息放到一个byte[]如果byte大小不够,分为多次。

服务器把信息发送可以依靠客户端所在的id或全部发。

所有数据转换为Default
private Encoding encoding = Encoding.Default;

ClientSocket[i]存放不如使用list来存放,因为这个长度固定,在很多机器连接断开就没了,不过这个是简单的,所以用了ClientSocket[i]

端口号都被写成没法修改,这个可以放在view一个textbox来修改

生成addressBook界面
先做一个ViewModel
viewaddressBook.cs

因为需要访问_model,在构造传入viewModel初始的_model

        public viewaddressBook(model.model _model)
        {
            this._model = _model;
        }

WPF跨线程访问线程安全的数据(如解决:该类型的CollectionView不支持从调度程序线程以外的线程对其SourceCollection)

更新数据中途出现了该类型的CollectionView不支持从调度程序线程以外的线程对其SourceCollection
查到了使用invoke就可以

从输入一个string然后更新

        private void newaddressBook(string str)
        {
            try
            {
                ObservableCollection<caddressBook> temp = DeserializeObject<caddressBook>(str);

                System.Windows.Application.Current.Dispatcher.Invoke
                (() =>
                {
                    addressbook.Clear();

                    foreach (var t in temp)
                    {
                        addressbook.Add(t);
                    }
                });
            }

            catch (JsonException e)
            {
                reminder = "输入不是ObservableCollection<caddressBook> json" + e.Message;
            }
        }

读取信息null

在运行返回一个错误
null
查询了是读取有一个null

            const string id = "id";
            const string MTIME = "MTIME";
            const string PLACE = "PLACE";
            const string INCIDENT = "INCIDENT";
            const string CONTACTSID = "NAME";
            using (SqlConnection sql = new SqlConnection(connect))
            {
                sql.Open();
                using (SqlCommand cmd = new SqlCommand(strsql , sql))
                {
                    using (SqlDataReader read = cmd.ExecuteReader())
                    {
                        if (!read.HasRows)
                            return diary;
                        int idindex = read.GetOrdinal(id);
                        int MTIMEindex = read.GetOrdinal(MTIME);
                        int PLACEindex = read.GetOrdinal(PLACE);
                        int INCIDENTindex = read.GetOrdinal(INCIDENT);
                        int CONTACTSIDindex = read.GetOrdinal(CONTACTSID);
                        while (read.Read())
                        {
                            diary.Add(new cdiary()
                            {
                                id = read.GetInt32(idindex).ToString() ,
                                MTIME = read.GetDateTime(MTIMEindex).ToString() ,
                                PLACE = read.GetString(PLACEindex) ,
                                incident = read.GetString(INCIDENTindex) ,
                                CONTACTSID = read.GetString(CONTACTSIDindex)
                            });
                        }
                    }
                }
            }

里面有些是null
使用

PLACE = read[PLACEindex] as string;

就可以

出现了把PLACE.Trim();错误可以使用

        private string DBNullstring<T>(object obj)
        {
            try
            {
                return obj == System.DBNull.Value ? " " : ( (T)obj ).ToString();
            }
            catch
            {
                return string.Empty;
            }
        }

读取发来数据需要时间

                byte[] MsgBuffer = new byte[65535];
                ClientSocket.BeginReceive(MsgBuffer , 0 , MsgBuffer.Length , SocketFlags.None , ar =>
                {
                    //对方断开连接时, 这里抛出Socket Exception
                    //An existing connection was forcibly closed by the remote host 
                    try
                    {
                        ClientSocket.EndReceive(ar);
                        ReceiveAction(encoding.GetString(MsgBuffer).Trim('\0' , ' '));
                        ReceiveCallBack(ReceiveAction);
                    }
                    catch (SocketException e)
                    {
                        reminder("对方断开连接" + e.Message);
                    }
                    catch(ObjectDisposedException e)
                    {
                        reminder (id.ToString() + "连接退出" + e.Message);
                        return;
                    }

MsgBuffer比发来信息小,那么分为多次,而在识别json会出现把字符串弄成多个,这样就出现json错误

需要在发送使用分开或使用大的buffer

连接数据库

连接数据库

$"Data Source={DataSource};Initial Catalog={InitialCatalog};Integrated Security=True";
DataSource 数据库ip
InitialCatalog 数据库名

strsql是sql语句

            using (SqlConnection sql = new SqlConnection(connect))
            {
                sql.Open();
                using (SqlCommand cmd = new SqlCommand(strsql , sql))
                {
                    using (SqlDataReader read = cmd.ExecuteReader())
                    {
                        try
                        {
                            if (!read.HasRows)
                                return null;
                            //读数据
                        }
                        catch
                        {

                        }
                    }
                }
            }

数据库获得数据

从数据库获得数据可以使用SqlDataReader read = cmd.ExecuteReader()
读取read的内容
连接

            const string addressBookname = "vaddressbook";
            string sqlAddressBook = $"{usesql}{line}SELECT * FROM {addressBookname};";

使用read[str]可以获得所在数据,

            const string id = "id";
            const string name = "name";
            const string contact = "contact";
            const string caddress = "caddress";
            const string city = "city";
            const string comment = "comment";

获得字符串所在

                        int idindex = read.GetOrdinal(id);
                        int nameindex = read.GetOrdinal(name);
                        int contactindex = read.GetOrdinal(contact);
                        int caddressindex = read.GetOrdinal(caddress);
                        int cityindex = read.GetOrdinal(city);
                        int commentindex = read.GetOrdinal(comment);
                             caddressBook temp = new caddressBook
                            {
                                id = read.GetInt32(idindex).ToString() ,
                                name = read.GetString(nameindex).Trim() ,
                                contact = read.GetString(contactindex).Trim() ,
                                address = read.GetString(caddressindex).Trim() ,
                                city = read.GetString(cityindex).Trim() ,
                                comment = read.GetString(commentindex).Trim()
                            };

这种 方法使用比较难,因为需要写很多字符串和int。

对string可以直接str=read[str] as string;

发送数据

        public void send(string str)
        {
            if (ClientSocket.Connected)
            {
                byte[] buffer = encoding.GetBytes(str);
                ClientSocket.Send(buffer , 0 , buffer.Length , SocketFlags.None);
            }
            else
            {
                try
                {
                    access(ip);                   
                }
                catch(SocketException e)
                {
                    reminder ("连接失败 " + e.Message);
                }
                catch(InvalidOperationException e)
                {
                    reminder("服务器没有开启"+e.Message);
                }
            }
        }

客户端可以设置ip

                <TextBlock Text="ip" />
                <TextBox Text="{Binding Path=_model.ip,Mode=TwoWay}" Width="100"/>
                <Button Content="确定" Click="确定"/>

添加通讯

        public void add()
        {
            if (accord())
            {
                foreach (var t in laddressBook)
                {
                    if (addressbook_equals(addressBook, t))
                    {
                        warn = "信息重复";
                        return;
                    }
                }
                _model.send(ecommand.addaddressBook , addressBook.ToString());
                reminder = "添加通讯";
                addressBook = new caddressBook();
            }
        }

查询可以没有输入为*

删除,判断有没修改,如果没有发送删除的类

            if (addressBook.Equals(_item))
            {
                _model.send(ecommand.daddressBook , _item.ToString());
                reminder = "删除通讯";
            }

通讯录 日记都一样,只是改了名字和一些,日记需要时间,所以判断是否存在时间,如果有,格式是否正确。

程序难在写了好多次不同的数据,这些可以合并为一个,然后修改,看到通讯录重复,没有去把重复的作为一个类,每个都写一次,如果要修改,经常出错,git可以撤销

git reset --hard id

代码:https://code.csdn.net/lindexi_gd/lindexi_gd/tree/master/%E4%B8%AA%E4%BA%BA%E4%BF%A1%E6%81%AF%E6%95%B0%E6%8D%AE%E5%BA%93

<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li/>').text(i)); }; $numbering.fadeIn(1700); }); }); </script>
分享到:
评论

相关推荐

    c/s模式的网上聊天室(c#)

    在信息技术领域,C/S(Client/Server)模式是一种常见的网络应用架构,广泛应用于各种系统开发,其中包括我们今天要探讨的网上聊天室。C/S模式的核心思想是将应用程序的功能分为客户端和服务器端两部分,客户端负责...

    C#局域网连接数据库程序

    在C#中连接数据库,通常会使用ADO.NET框架,它是.NET Framework的一部分,提供了与各种数据库管理系统(如SQL Server、Oracle、MySQL等)交互的能力。ADO.NET主要包括以下组件: 1. **Connection对象**:用于建立和...

    C# 局域网通信

    总的来说,利用C#和WPF实现局域网通信是一个涉及网络编程、文件操作和用户交互的综合性项目。通过以上步骤,开发者可以构建一个功能完善的文件和图片共享平台,同时实现基本的聊天功能。在实践中,开发者需要不断...

    C# WPF内网文件传输.zip

    在C#编程环境中,Windows Presentation Foundation(WPF)是一个强大的框架,用于构建具有丰富用户界面的桌面应用程序。本文将深入探讨如何使用C# WPF进行内网文件传输,这是一个对于网络编程和桌面应用开发者非常...

    C#编写的超简单局域网聊天程序

    标题中的"C#编写的超简单局域网聊天程序"揭示了这个项目是使用C#编程语言构建的一个局域网通信应用。C#是Microsoft开发的一种面向对象的编程语言,广泛用于开发Windows桌面应用、Web应用以及游戏等。在这个场景中,...

    C#(WPF)获取本地IP地址 C#编程

    在C#编程中,Windows Presentation Foundation (WPF)是一个用于构建桌面应用的框架,而获取本地IP地址是网络编程中的常见需求。这篇文章将详细介绍如何在C# WPF应用中实现这个功能,适合初学者学习。 首先,我们...

    局域网ping工具(WPF)

    通过学习和实践这样的项目,开发者不仅可以提升WPF应用开发技能,还能深入了解网络诊断和数据库管理,同时增强对多线程和并发处理的理解。对于初学者,这是一个很好的练习项目,有助于综合运用多种技术知识。而对于...

    wpf实现wifi功能

    wpf实现wifi功能

    基于C#的局域网应用商店程序

    综上所述,"基于C#的局域网应用商店程序"项目涵盖了从基础编程到网络通信,再到UI设计的多个重要知识点,是一个综合性的C#项目实践。通过学习和实现这样的项目,开发者可以提升在C#编程、GUI设计以及网络应用开发等...

    C#WPF版文字消息、语音视频通话、文件传输等功能的即时通讯软件源码

    5.FileShare目录是我要写的程序共享台,前台依然是WPF的但是没写完,.NET REMOTING的 注意: 数据库连接字符串配置在服务器端进行配置。 运行程序,要先启动服务端,在启动客服端程序 数据库放在:DB文件夹下

    C# 仿QQ局域网聊天系统

    【标题】"C# 仿QQ局域网聊天系统"是一个使用C#编程语言开发的、模拟QQ功能的局域网通信应用。该系统旨在实现类似QQ的基本通信功能,允许用户在同一个局域网内进行单人或群组聊天。 【描述】中提到,这个项目的核心...

    c# 模仿qq的局域网通信源码实现视频聊天功能

    在本文中,我们将深入探讨如何使用C#编程语言模仿QQ的局域网通信源码来实现视频聊天功能。QQ作为一款流行的即时通讯软件,其在局域网内的视频聊天功能深受用户喜爱。为了构建类似的系统,我们需要理解并掌握以下几个...

    TCP 聊天 局域网 c#

    总的来说,“TCP聊天 局域网 c#”项目是一个实践TCP/IP通信、C#编程以及局域网应用的好例子,对于学习网络编程和软件开发有着很高的参考价值。通过深入理解和实践该项目,开发者可以掌握网络通信的基础知识,提升...

    wpf 视频聊天系统

    【标题】"wpf 视频聊天系统"是基于Windows Presentation Foundation(WPF)框架开发的一个实时通信平台,主要用于实现用户间的视频通话功能。在IT领域,WPF是一种微软提供的.NET Framework应用程序界面(UI)开发...

    c#局域网聊天工具仿QQ

    这个项目利用了socket通信技术,构建了一个客户端-服务器(C/S)架构,使得用户可以在同一个网络环境下进行即时的文字交流、图片分享以及文件传输。 【描述】该工具的设计和实现包含了多个关键的技术点: 1. **...

    C#版局域网五子棋/围棋示例

    总的来说,C#版局域网五子棋/围棋示例项目结合了C#的基础知识、棋类游戏的规则实现以及网络通信技术,是学习游戏开发和网络编程的绝佳实践。通过这个项目,开发者不仅可以掌握C#语言特性,还能了解到游戏逻辑的设计...

    C#局域网桌面共享

    本例中的"C#局域网桌面共享"项目旨在实现一个能够进行局域网内文件传输、桌面截屏以及图片压缩功能的软件。这个软件使得在同一网络环境下的用户可以方便地共享他们的桌面视图,提高协作效率。 首先,我们来详细讨论...

    c#局域网传文件源码

    在C#/.NET环境下,局域网内进行文件传输是一项常见的任务,这通常涉及到网络编程、多线程处理以及文件I/O操作等技术。本文将深入解析“c#局域网传文件源码”所涉及的关键知识点,并提供相关实现思路。 1. **网络...

    局域网群聊

    局域网群聊是一种在有限网络...综上所述,局域网群聊项目涉及到C#编程、WPF界面设计、网络通信、多线程、异步编程等多个方面,是一个综合性的学习实践项目。通过这样的项目,开发者可以深入理解并掌握这些关键技能。

    C#局域网聊天发送文件

    在本文中,我们将深入探讨如何使用C#编程语言开发一个局域网聊天应用程序,特别是侧重于文件发送功能。C#是一种强大的、面向对象的编程语言,由微软公司开发,广泛应用于Windows桌面应用、游戏开发以及服务器端编程...

Global site tag (gtag.js) - Google Analytics