c#局域网_c#局域网内发送文件 - CSDN
  • 需求:1、服务器Server:2、客户端Client:3、客户端发送消息到服务器,服务器接收到消息后显示并且发送确认信息。 服务器代码如下所示:using System;using System.Collections.Generic;using System.Linq;...

    需求:

    1、服务器Server:

    2、客户端Client:

    3、客户端发送消息到服务器,服务器接收到消息后显示并且发送确认信息。

     

    服务器代码如下所示:

    客户端代码如下所示:

    运行结果如下所示:

     实验结果

    缺陷:

    (1) 不能实时进行对话

    (2) 不能手工进行关闭连接

    展开全文
  • C#局域网通信

    2019-08-12 21:32:04
    在合作当中,我们要实现局域网聊天这个功能,看了很多大佬们的博客,发现大佬们都真是太厉害了,发现自己有待提高的地方还很多。 以下是我实现这项功能的图示和代码,如有更好的办法,下方评论指出,本人将感谢大佬...

    在合作当中,我们要实现局域网聊天这个功能,看了很多大佬们的博客,发现大佬们都真是太厉害了,发现自己有待提高的地方还很多。

    以下是我实现这项功能的图示和代码,如有更好的办法,下方评论指出,本人将感谢大佬们的建议和解决方案!

    第一步:首先看下界面和命名

    第二步:代码

    服务器端:

    From界面:

    public Form1()
            {
                InitializeComponent();
                CheckForIllegalCrossThreadCalls = false;
            }
            server s = new server();
            IPAddress ip = null;
            private void Form1_Load(object sender, EventArgs e)
            {
                ip = Dns.Resolve(Dns.GetHostName()).AddressList[0];
                this.txtIP.Text = ip.ToString();
                this.s.Started += new EventHandler(s_Started);
                this.s.Logged += new EventHandler<UserLoggedEventArgs>(s_Logged);
                this.s.PChated += new EventHandler<PublicChatEventArgs>(s_PChated);
            }
    
            private void BtnSend_Click(object sender, EventArgs e)
            {
                string msg = "CHAT|服务器消息:|" + DateTime.Now.ToLongTimeString() + "|" + this.rtxtMsg.Text;
                this.s.SendMessage(msg);
                this.rtxt.AppendText("服务器消息:在" + Convert.ToDateTime(DateTime.Now.ToLongTimeString()) + " 通知:\n" + this.rtxtMsg.Text + "\n");
                this.rtxtMsg.Text = "";
            }
    
            void s_PChated(object sender, PublicChatEventArgs e)
            {
                this.rtxt.AppendText(e.UserName + " 在" + e.Time + "说: \n" + e.Msg + "\n");
            }
    
            void s_Started(object sender, EventArgs e)
            {
                this.rtxt.AppendText("******************服务器已启动******************\n");
            }
    
            void s_Logged(object sender, UserLoggedEventArgs e)
            {
                this.rtxt.AppendText("客户端【 " + e.UserName + "】 已启动!\n");
                this.lbxUserList.Items.Clear();
                foreach (string item in e.UserList)
                {
                    this.lbxUserList.Items.Add(item);
                }
            }
    
            private void BtnStart_Click(object sender, EventArgs e)
            {
                this.s.ip = ip;
                this.s.port = int.Parse(this.txtPort.Text);
                this.s.Start();
                this.btnStart.Enabled = false;
            }
    
            private void Rtxt_TextChanged(object sender, EventArgs e)
            {
                this.rtxt.Focus();
                this.rtxtMsg.Focus();
            }

     

    server类:

     public event EventHandler Started;
            public event EventHandler<UserLoggedEventArgs> Logged;
            public event EventHandler<PublicChatEventArgs> PChated;
    
            public server() { }
    
            #region 字段定义
            public IPAddress ip { get; set; }
            public int port { get; set; }
            Thread thread = null;
            private TcpListener listener;
            private Dictionary<string, Socket> userlist = new Dictionary<string, Socket>();
            #endregion
    
            //开启服务
            public void Start()
            {
                this.thread = new Thread(new ThreadStart(this.Work));
                this.listener = new TcpListener(this.ip, this.port);
                this.listener.Start();
                this.thread.Start();
                if (this.Started != null)
                {
                    this.Started(this, new EventArgs());
                }
            }
    
            public void Work()
            {
                while (true)
                {
                    Socket soket = this.listener.AcceptSocket();
                    Thread userThread = new Thread(
                             delegate ()
                             {
                                 ResponseClient(soket);
                             }
                        );
                    userThread.Start();
                }
    
            }
    
            private void ResponseClient(Socket soket)
            {
                while (true)
                {
                    byte[] buffer = new byte[1024 * 10];
                    soket.Receive(buffer);
    
                    string msg = Encoding.Unicode.GetString(buffer).TrimEnd('\0');
                    string[] tokens = msg.Split('|');
                    if (tokens[0] == "CONN")
                    {
                        if (this.userlist.ContainsKey(tokens[0]))
                        {
                            break;
                        }
                        else
                        {
                            this.userlist.Add(tokens[1], soket);
                        }
                        UserLoggedEventArgs e1 = new UserLoggedEventArgs();
                        e1.UserName = tokens[1];
                        e1.UserList = this.GetUserList();
                        //通知服务器界面
                        if (this.Logged != null)
                        {
                            this.Logged(this, e1);
                        }
                    }
    
                    if (tokens[0] == "TS")
                    {
                        PublicChatEventArgs e1 = new PublicChatEventArgs();
                        e1.UserName = tokens[1];
                        e1.Time = Convert.ToDateTime(tokens[2]);
                        string message = "";
                        for (int i = 3; i < tokens.Length; i++)
                        {
                            message += tokens[i];
                        }
                        e1.Msg = message;
                        if (this.PChated != null)
                        {
                            this.PChated(this, e1);
                        }
                    }
                }
            }
    
            //获取客户列表
            private List<string> GetUserList()
            {
                List<string> list = new List<string>();
                foreach (KeyValuePair<string, Socket> item in userlist)
                {
                    list.Add(item.Key);
                }
                return list;
            }
    
            public void SendMessage(string message)
            {
                foreach (KeyValuePair<string, Socket> item in userlist)
                {
                    byte[] buffer = Encoding.Unicode.GetBytes(message.ToCharArray());
                    item.Value.Send(buffer);
                }
            }
        }
        public class UserLoggedEventArgs : EventArgs
        {
            public string UserName { get; set; }
            public List<string> UserList { get; set; }
        }
    
        public class PublicChatEventArgs : EventArgs
        {
            public string UserName { get; set; }
            public string Msg { get; set; }
            public DateTime Time { get; set; }
            public string Font { get; set; }
            public string FontColor { get; set; }
            public string FontSize { get; set; }
    
        }

    用户界面:

    From界面:

     public event EventHandler Started;
            public event EventHandler<UserLoggedEventArgs> Logged;
            public event EventHandler<PublicChatEventArgs> PChated;
    
            public server() { }
    
            #region 字段定义
            public IPAddress ip { get; set; }
            public int port { get; set; }
            Thread thread = null;
            private TcpListener listener;
            private Dictionary<string, Socket> userlist = new Dictionary<string, Socket>();
            #endregion
    
            //开启服务
            public void Start()
            {
                this.thread = new Thread(new ThreadStart(this.Work));
                this.listener = new TcpListener(this.ip, this.port);
                this.listener.Start();
                this.thread.Start();
                if (this.Started != null)
                {
                    this.Started(this, new EventArgs());
                }
            }
    
            public void Work()
            {
                while (true)
                {
                    Socket soket = this.listener.AcceptSocket();
                    Thread userThread = new Thread(
                             delegate ()
                             {
                                 ResponseClient(soket);
                             }
                        );
                    userThread.Start();
                }
    
            }
    
            private void ResponseClient(Socket soket)
            {
                while (true)
                {
                    byte[] buffer = new byte[1024 * 10];
                    soket.Receive(buffer);
    
                    string msg = Encoding.Unicode.GetString(buffer).TrimEnd('\0');
                    string[] tokens = msg.Split('|');
                    if (tokens[0] == "CONN")
                    {
                        if (this.userlist.ContainsKey(tokens[0]))
                        {
                            break;
                        }
                        else
                        {
                            this.userlist.Add(tokens[1], soket);
                        }
                        UserLoggedEventArgs e1 = new UserLoggedEventArgs();
                        e1.UserName = tokens[1];
                        e1.UserList = this.GetUserList();
                        //通知服务器界面
                        if (this.Logged != null)
                        {
                            this.Logged(this, e1);
                        }
                    }
    
                    if (tokens[0] == "TS")
                    {
                        PublicChatEventArgs e1 = new PublicChatEventArgs();
                        e1.UserName = tokens[1];
                        e1.Time = Convert.ToDateTime(tokens[2]);
                        string message = "";
                        for (int i = 3; i < tokens.Length; i++)
                        {
                            message += tokens[i];
                        }
                        e1.Msg = message;
                        if (this.PChated != null)
                        {
                            this.PChated(this, e1);
                        }
                    }
                }
            }
    
            //获取客户列表
            private List<string> GetUserList()
            {
                List<string> list = new List<string>();
                foreach (KeyValuePair<string, Socket> item in userlist)
                {
                    list.Add(item.Key);
                }
                return list;
            }
    
            public void SendMessage(string message)
            {
                foreach (KeyValuePair<string, Socket> item in userlist)
                {
                    byte[] buffer = Encoding.Unicode.GetBytes(message.ToCharArray());
                    item.Value.Send(buffer);
                }
            }
        }
        public class UserLoggedEventArgs : EventArgs
        {
            public string UserName { get; set; }
            public List<string> UserList { get; set; }
        }
    
        public class PublicChatEventArgs : EventArgs
        {
            public string UserName { get; set; }
            public string Msg { get; set; }
            public DateTime Time { get; set; }
            public string Font { get; set; }
            public string FontColor { get; set; }
            public string FontSize { get; set; }
    
        }

    ClientUI类:

     public class ClientUI
        {
    
            public ClientUI() { }
    
            public event EventHandler Started;
            public event EventHandler<UserLoggedEventArgs> Logged;
            public event EventHandler<PublciChatEventArgs> PChated;
    
            public string clientName { get; set; }
            public string msg { get; set; }
            public IPAddress ip { get; set; }
            public int port { get; set; }
            TcpClient client = new TcpClient();
            Stream stream;
            Thread mainThread = null;
    
            //连接服务器
            public void Connect()
            {
                this.client.Connect(this.ip, this.port);
                this.stream = this.client.GetStream();
                this.clientName = Guid.NewGuid().ToString().Substring(0, 10);
                string message = "CONN|" + this.clientName;
                this.SendMessage(message);
    
                this.mainThread = new Thread(new ThreadStart(this.ResponseServer));
                this.mainThread.Start();
    
                if (this.Started != null)
                {
                    this.Started(this, new EventArgs());
                }
            }
    
            public void ResponseServer()
            {
                while (true)
                {
                    byte[] buffer = new byte[1024 * 10];
                    this.stream.Read(buffer, 0, buffer.Length);
                    string message = Encoding.Unicode.GetString(buffer).TrimEnd('\0');
                    string[] tokens = message.Split('|');
    
                    if (tokens[0] == "CHAT")
                    {
                        PublciChatEventArgs e1 = new PublciChatEventArgs();
                        e1.UserName = tokens[1];
                        e1.Time = Convert.ToDateTime(tokens[2]);
                        string msg = "";
                        for (int i = 3; i < tokens.Length; i++)
                        {
                            msg += tokens[i];
                        }
                        e1.Msg = msg;
                        if (this.PChated != null)
                        {
                            this.PChated(this, e1);
                        }
                    }
                }
            }
    
            public void ChartS(string message)
            {
                this.msg = "TS|" + this.clientName + "|" + DateTime.Now.ToLongTimeString() + "|" + message;
                this.SendMessage(msg);
    
            }
    
            public void SendMessage(string message)
            {
                byte[] buffer = Encoding.Unicode.GetBytes(message.ToCharArray());
                this.stream.Write(buffer, 0, buffer.Length);
            }
        }
        public class UserLoggedEventArgs : EventArgs
        {
            public string UserName { get; set; }
            public List<string> UserList { get; set; }
        }
         public class PublciChatEventArgs : EventArgs
        {
            public string UserName { get; set; }
            public string Msg { get; set; }
            public DateTime Time { get; set; }
            public string Font { get; set; }
            public string FontColor { get; set; }
            public string FontSize { get; set; }
        }

     

    展开全文
  • 毕业论文-基于C#局域网通信

    千次阅读 2018-08-26 13:03:13
     局域网即时通讯工具的设计与实现 PS:等有空了,放源码讲解吧。。。。 目录 局域网即时通讯工具的设计与实现 1.引言 1.1课题背景及意义 1.2发展现状 1.2.1产品同质化的现象严重 1.2.2产品定位不够精准 ...

     

                                  局域网即时通讯工具的设计与实现

    PS:等有空了,放源码讲解吧。。。。

    目录

    局域网即时通讯工具的设计与实现

    1.引言

    1.1课题背景及意义

    1.2发展现状

    1.2.1产品同质化的现象严重

    1.2.2产品定位不够精准

    1.3系统目标

    1.3.1显示主机名称及IP地址

    1.3.2收发文件、发送实时图像及发送录音

    1.3.3历史记录和下线刷新

    1.4运行环境及开发语言

    1.4.2开发运行环境的

    1.4.3系统开发语言

    2.相关开发技术

    2.1WPF(Windows Presentation Foundation)

    2.2C/S模式

    2.3多线程编程技术

    2.3.1进程与线程

    2.3.2多线程、线程池

    2.4TCP/UDP协议

    2.5Winsock网络编程

    3.系统需求分析

    3.1系统总体需求分析

    3.2系统流程图

    3.2.1发送端流程图

    3.2.2接收端流程图

    3.3系统可行性分析

    3.3.1技术可行性

    3.3.2经济可行性

    3.3.3操作可行性

    4.系统设计

    4.1系统总体设计

    4.2主界面的设计

    4.3文字聊天模块

    4.3.1文字聊天

    4.3.2文字聊天流程图

    4.4文件传输模块

    4.5截图模块

    4.6录音模块

    4.7历史记录模块

    4.7.1数据库设计

    4.7.2各种类型信息的记录

    4.7.3历史消息的显示界面

    5.总结和展望

    5.1总结

    5.2展望

    参考文献

     

     

    1.引言

     

    1.1课题背景及意义

    互联网的蓬勃兴起,促进了基于因特网的即时通讯技术的迅速发展。自1998年以来,即时通讯行业发展迅速,其功能日益丰富。如今即时通讯已经发展成一种综合化信息平台,实现终端联网的即时通讯服务[1]。即时通讯是在因特网上扩展会话和分散通信方式的实例[2]。但作为社交工具[3],部分即时通讯软件并不满足有特定需求的用户群体,如对内部网络和Internet的接入有严格限制的用户。部分主流即时通讯软件存在如下问题:①广告等无关信息的不断推送;②对Internet网络的极度依赖;③基本功能之外的扩展功能庞多[4]。而局域网即时通讯工具能有效地解决上述问题[5],有效地提高网络资源利用率。 

    1.2发展现状

    1.2.1产品同质化的现象严重

    腾讯QQ,最开始是通过模仿ICQ起步的。在随后的发展中,通过不断创新,逐步成长起来,甚至超越了ICQ已有的成就,在我国即时通讯市场占有率达到了第一。这种效应模式也被后来许多公司模仿,但部分公司通常会直接模仿,而不进行创新。所以目前,我国即时通讯市场上的软件同质化程度高[6]。

    1.2.2产品定位不够精准

    目前,我国的即时通讯软件大部分属于娱乐为主,功能为辅的类型。开发出的应用功能,基本上都是为娱乐服务的。由于市场化经济的刺激,使得很多通讯工具的功能为了体现新颖,目的是为了吸引用户下载使用。但是,由于目前即时通讯工具庞杂,各类新颖的功能也层出不穷,使得许多功能不适用于用户群体,导致功能虽然看上去新颖,但是明显觉得多余,甚至是由于某些新颖的功能,而让用户放弃使用[7]。

    1.3系统目标

     

    1.3.1显示主机名称及IP地址

     

    在程序启动时,使用Winsock获取本机主机名称及MAC地址,将信息封装到UDP数据包中,每两秒在局域网中广播一次。局域网内的其他主机通过解析广播包,获取到本机的名称、MAC地址和IP地址。然后在系统的主界面能够显示局域网中其它已经安装并运行该工具的主机名称和IP地址,使用MAC地址标记各主机的昵称。同时,可以和其它主机进行文字聊天。

    1.3.2收发文件、发送实时图像及发送录音

    任何一台主机可以和其它主机进行收发文件,包括但不限于WORD、PPT、ZIP等文件格式。其次,实现类似QQ的实时截图功能。通过获取整个屏幕图片,利用鼠标选取特定区域,向选定主机发送。同时,通过调用winmm.dll中的mciSendString方法实现录音功能,点击录制语音,可发送给选定的主机。

    1.3.3历史记录和下线刷新

    保留与其它主机的通信信息,通过将历史记转换成特定格式存储到数据库,以达到保存历史记录到本地的功能。在系统下次启动后,用户能查阅之前的历史记录,也可以选择清空历史记录。但清空记录并不删除已经接受的文件和截图。

    1.4运行环境及开发语言

     

    1.4.2开发运行环境的

     

    本系统是一个面向中小型企业机构,满足内部通讯需要的局域网即时通讯系统。开发此系统所需的基本软、硬件环境为:

    (1).操作系统:Windows XP 64bit、Windows 7 64bit及Windows 8等其它64位操作系统

    (2) 内存:2G以上内存

    (3) 处理器:Intel Pentium PIII或更高处理器。

    (4) 通讯网络:局域网

    1.4.3系统开发语言

    本系统使用C#语言在VS2012平台上开发。C#是基于C/C++的面向对象的编程语言。它的主要优点:一是具有优异的快速开发能力,二是支持面向对象的方法[8]。

     

    2.相关开发技术

     

    2.1WPF(Windows Presentation Foundation)

    WPF是为.NET框架设计的全新的软件界面显示系统。为了方便软件开发人员使用该系统的功能,微软提供了一个编程类库。这个编程类库具有以下四点特性:1、对用户界面功能更广泛的支持和融合。2、声明式脚本语言的引入与正式支持。3、更简单的安装与配置4、更新的文字排版支持[9]。

    同时,比较基于GDI的图形界面程序拥有以下优越的特性:1、显示图形的设备无关性。2、更高的画面精度。3、对界面重叠的更好的处理。4、WPF显示使用了硬件加速。5、通过脚本控制界面执行效果。6、WPF的可移植性[9]。

    2.2C/S模式

    直接或间接地通过网络协议与其他计算机进行通信,是网络编程的目的。其的基本模型是客户机/服务器模型(Client/Server Model,简称C/S模式)[10]。而C/S模式在实际应用操作过程中采取主动请求方式,在客户进程发出请求完全是随机的,同时,可能有若干个用户请求连接同一个服务器。这就要求服务器具有解决并发请求的能力[11]。

    2.3多线程编程技术

     

    2.3.1进程与线程

     

    在Windows系统中,系统具有同时运行若干个程序的能力,而每个运行中的程序就是一个进程。进程是操作系统结构的基础。线程是进程中的一个实体。线程之间的相互制约,会导致线程在运行中呈现出间断性[12]。

    2.3.2多线程、线程池

    通过运行单个程序来创建多个线程来完成各自的功能,从而提高CPU的利用率。但多线程具有明显缺点:1、线程数量越多,系统内存消耗越大。2、为了管理并协调这些线程,需要CPU花费更多的时间跟踪。3、当线程之间访问共享资源时,可能会导致不可预知的问题。

    而线程池,能弥补线程的部分缺点。通过有限固定的少量线程执行大量程序代码,从而减少创建与销毁线程带来的性能开销。通过设置最大并发线程数,解决线程之间访问共享资源的问题。

    2.4TCP/UDP协议

    UDP(User Datagram Protocol):用户数据包协议,是无连接、不可靠的传输层协议,提供尽力服务但不保证数据的完整性。但相比较于TCP一对一的连接,UDP能提高广播和多播服务。广播(Broadcastinig)使用广播地址255.255.255.255(需要指明接收者的端口号),可以将信息发送到在同一网络内的所有主机。同时为了避免未来瘫痪,路由器不会转发本地广播信息。多播,即对同一网络中部分主机进行了逻辑分组。在数据接收发送时,数据包在网络中传播,分组内的主机会对数据作出响应,而没有被划入这个分组的主机将在数据链路层丢弃这些数据包。

    TCP(Transmission Control Protocol):TCP是面向连接的通信协议,所以只能用于端到端的通讯。TCP层将包排序并进行错误检查,同时实现虚拟电路间的连接[13]。

    2.5Winsock网络编程

    在编程中涉及到网络访问控制的开发人员可直接引用System.Net.Sockets命名空间。该命名空间封装有Winsock(Windows Sockets) 接口的托管实现,。Socket是计算机进行通信的端口,是相关网络应用程序设计中的重要的概念[14]。

    在实际编程中,直接使用Socket类,可以获得更多的控制,可以使用不同的协议,不仅包括基于TCP或UDP的协议,还可以自定义自己的协议,更多地控制基于TCP或UDP的协议。接收数据的方法有两种:Socket类的Receive方法和NetworkStream的Read方法,发送数据也有对应的两种方法:Socket类的Send方法和NetworkStream的Wtire方法[15]。

    NetworkStream类能保证用户发送的数据,在不需要用户管理的情况下,自动地全部发送到TCP缓冲区,大大简化了编程工作,同时还提供了许多实用的属性和方法,所以在实际编程中,应用的较多。

     

    3.系统需求分析

     

    3.1系统总体需求分析

    本系统是一个局域网内的即时通讯工具,根据毕业设计需求,本系统将分为五个系统:1、简单文字聊天子系统,在局域网中选择同样安装本系统的用户,可以一对一发送简单的文字信息。2、文件传输子系统,将文件转化成文件比特流,传输到选定的用户,再转化还原成文件。3、仿QQ截图子系统,捕捉并显示整个屏幕的图像,通过相应的鼠标事件,可以选取图像的部分,发送给选定的用户。4、简单录音子系统,点击录制语音信息,可发送给选定的用户。5、历史信息存储子系统,记录与每个用户的聊天信息(包括文字信息、文件、截图),形成相应的记录存储在数据库SQLite中。本系统的功能类似飞鸽传书软件。在设计系统界面时,按照简洁、直观的特点安排,在编程时应充分考虑UDP(User Datagram Protocol)及TCP(Transmission Control Protocol的优缺点,实现局域网内用户之间沟通便捷,资源共享快速。

    3.2系统流程图

    3.2.1发送端流程图

     

    图3-1是发送端主机发送信息的流程图。在启动程序时,会根据局域网中的广播报文生成相应的用户主机列表。选择需要聊天的主机,根据传输的信息不同,转换成相应的比特流并封装,然后发送给目标主机。

                                                                               图3-1 发送端业务流程图

    3.2.2接收端流程图

    图3-2是接收端主机接收信息的流程图。在启动程序时,根据广播信息生成相应的用户主机列表。接收到数据并作分析处理。根据信息类型的不同,生成相应的记录并显示在对应的地方。其中文件信息,需要用户判断是否接受。若不接受,将舍弃。若接受,则做与其他类型相似的处理。

                                                                               图3-2 接收端业务流程图

    3.3系统可行性分析

    3.3.1技术可行性

     

    本系统是为方便局域网内部人员交流沟通开发的。具体设计实现涉及到C#编程、TCP/IP 协议及WinSock网络编程、多线程编程技术。而本人在之前的大学课程中均有所涉及,借此机会,更加深入地学习、理解。

    3.3.2经济可行性

    成本方面:由于本系统的设计与实现属于教学科研的一个环节,并且由指导老师义务指导。所以开发本系统的经济成本是低的。

    效益方面:开发一个合理的系统,可大大节约网络资源,曾经依赖Internet的接入传输的信息,现在使用本系统就可以在局域网传输,大大减少数据报跳转的路由数量。综合考虑以后,开发本系统的经济可行性高。

    ​​​​​​​3.3.3操作可行性

    本系统的目的是方便局域网内部人员。并且由于系统功能简单,其相应的界面简洁,用户只需通晓简单的电脑操作知识,就能自由地应用本软件。

     

    4.系统设计

     

    4.1系统总体设计

    本系统主要分为五个部分:1、简单文字聊天。2、文件传输。3、仿QQ截图。4、简单录音。5、历史记录。所以接下来将系统分为五大模块来介绍。

    本系统设计实现时,关键的部分在于如何在局域网中发送接收数据,并对接收的数据进行解析。在本系统中,发收数据是采用C/S结构,每个运行在电脑的系统即是客户端又是服务端。在本系统中,UDP用于发送上线下线的数据包,TCP用于发送文本、文件、截图的数据包。在系统启动时,会同时启动三个线程:

    1、用UDP广播方式广播本机上线信息:

    每两秒发送一个UDP广播包,封装的数据为,表示加入聊天系统的字符串“JOIN”,即自定义的数据类型,随后是本机用于网络通信的网卡的MAC地址,最后一部分是本机的主机名

    2、在本地所有IP地址的8001端口监听任意IP地址发出的UDP报文:

    按照自定义封装的数据类型解析。如果是“JOIN”类的数据包,按MAC地址查询数据库,检查是否有相应的昵称记录,有就返回,反之就将新用户插入数据库。在主界面显示出数据包分析得出的用户信息。如果是“LEAV”类数据包(当系统关闭时会发出一个“LEAV”类数据包),则说明有用户下线,在主界面移除数据包分析得出的用户信息。

    3、在本地所有IP地址的11000端口监听其它主机的TCP连接请求:

    设置监听最大连接个数为100.每接收到一个请求,都会新建一个套接字(用于连接发出这个请求的主机),并新开线程处理这个新连接的数据接收,原线程继续监听。所有对已接收数据的处理都封装在ChatSession类中(对数据包的处理主要都在ChatSession类的StartChat方法中)。数据包内容的开头设置字符表达数据的类型,“MESS”表示,是普通的文本信息转化成的数据。“FILE”表示,是文件转化成的数据。“PICT”表示,是图片转化成的数据。不同类型的数据将在功能模块里面详细说明。但,不管是怎样的数据都会生成相应的记录插入到数据库中。

    其中UDP广播通知上线的主要代码为:

    public void BroadCast(object state) {

                UdpClient udpClient = new UdpClient();

                IPEndPoint ep = new IPEndPoint(IPAddress.Broadcast, 8001);

                string message = "JOIN" + GetMacAddress() + (string)state;

                byte[] buff = Encoding.Default.GetBytes(message);

                while (!completed) {

                    udpClient.Send(buff, buff.Length, ep);

                    Thread.Sleep(2000);

                }

                udpClient.Close();

                return;

            }

    private static string GetMacAddress(){

                try{

                    string strMac = string.Empty;

                    ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");

                    ManagementObjectCollection moc = mc.GetInstances();

                    foreach (ManagementObject mo in moc){

                        if ((bool)mo["IPEnabled"] == true) {

                            strMac = mo["MacAddress"].ToString();

                            break;

                        }

                    }

                    moc.Dispose();

                    mc.Dispose();

                    return strMac;

                }

                catch{

                    return "unknown";

                }

            }

    其中UDP广播通知下线的主要代码为:

    public void Leave(string state) {

                UdpClient udpClient = new UdpClient();

                IPEndPoint ep = new IPEndPoint(IPAddress.Broadcast, 8001);

                string message = "LEAV" + state;

                byte[] buff = Encoding.Default.GetBytes(message);

                udpClient.Send(buff,buff.Length,ep);

                udpClient.Close();

                return;

            }

    4.2主界面的设计

    因为本系统的用户设计主要是针对用户在局域网内的日常活动,以及考虑到毕业设计的时间要求,所以本系统的界面较为简单,以便给用户提供一个上手快,理解简单的使用环境。为了方便用户选择单个用户发送信息,所以在主界面左侧设计了一个ListView,用于显示所有同一局域网内上线的用户,见图4-1,ListView的子项包括了用户名、IP地址及昵称(昵称存储在本地数据库)。为了方便用户辨别本机,将本机信息显示在界面上侧。

                                                                                        图4-1 主界面显示

     

           为了方便区分各个用户,添加了昵称功能。修改昵称的控件将显示在主界面的下侧。右击准备修改昵称的用户,可以编辑昵称,昵称将以MAC地址为主键存储在本地数据库,修改后在用户列表中实时刷新,系统下次启动还能显示。如图4-2.

                                                                                        图4-2  修改昵称

    点击任意一个用户,将出现与这个用户的聊天控件,控件将显示主界面的右侧,并显示这个用户发送给本机的未读信息。为了有条理的、直观地显示信息,设计了一个ListView用来显示。ListView的子项具有点击事件。

                                                                                      图4-3 聊天界面

    4.3文字聊天模块

    4.3.1文字聊天

     

    点击某个用户后,出现聊天控件,后台程序记录被点击的用户信息。同时,会启动一个新线程,不断查询数据库中是否有这个用户发送的未读信息。有就返回这些未读信息,将这些信息显示在当前显示消息的ListView中,并将这些未读信息更新为已都读。

           发送端:当需要向特定用户发送信息时,直接在右下的文本框中编辑,点击发送按钮,后台后台会获取文本框中的内容,将获取到的文本信息加上“MESS”的信息头部,再转换成比特数据。结合之前记录的用户信息,初始化套接字Socket为字符流方式的TCP通信,通过三次握手协议建立连接,实现点对点的数据传输,发送比特数据,关闭Socke连接,生成相应已读类型的记录更新到数据库,同时也将信息添加到显示信息的ListView中。

           接收端:通过协议建立连接,接收的数据包,调用ChatSession类的StartChat方法解析,如果是文本信息,生成标记为未读信息的记录插入到数据库中,接收完数据,关闭连接。文件、截图类信息,另行处理。

    因为一旦数据发送接收完就关闭连接,所以不需要考虑TCP数据包粘包的问题。

    ​​​​​​​4.3.2文字聊天流程图

    图4-4是文字聊天发送端流程图。用户在聊天列表中,点击接收信息的用户,后台会记录所选的用户。在文本框编辑需要发送的信息并点击“发送”按钮。将获取文本框内的信息并加上头部“MESS”,形成要发送的信息。通过编码将信息转换成比特流,在与目标主机建立连接后发送比特流,发送完毕则关闭连接。最后,形成相应的信息记录插入到数据库中。

                                                                               图4-4 文字聊天发送端流程图

    图4-4是文字聊天接收端流程图。在建立连接后,接收比特流数据。数据接收完,就关闭连接,分析比特流数据,得到文本信息。最后,生成对应的未读信息记录插入到数据库中。

                                                                               图4-5 文字聊天接收端流程图

    4.4文件传输模块

    系统的文件传输也要求尽量像文字聊天一样,简单易操作,同时充分发挥局域网的优势。其中,建立连接的部分和文字聊天中的一致。因为本系统中传输文件是有自定义的数据头部,实现带文件名的传输,因此接下来将着重介绍对文件的封装。

    点击用户,然后点击聊天控件中的发送文件按钮,将出现打开文件的对话框,如图4-5。选择文件并发送。后台获取文件路径,将对应文件使用FileStream类直接转换成文件流。使用自定义的FileNameHead类中GetBytes方法得到,图4-6中除文件流以外的比特部分。其中包括用来表示报文类型的“FILE”字段,文件名转化成比特流后的长度以及文件名的比特流,生成相应的已读类型的消息记录,更新到数据库及显示信息的ListView中。

                                                                               图4-5 打开文件对话框

           在图4-6中,除文件流以外部分的比特流,统一使用Unicode编码,文件名的比特流长度使用Int32类型的变量表示。所以FILE字段对应的比特流定长为8比特,文件名的比特流长度的比特流定长为 4比特,文件名的比特流及文件流不定长,但文件名的比特流长度可以通过解析前一个字段得到。因为一旦数据发送接收完就关闭连接,所以不需要考虑文件流长度不定的问题。

                                                                                            图4-6  TCP数据的内容

    主机接收文件数据时,会结合用户列表显示是哪个主机发送的,并询问是否接收,如图4-7。如果选“是”,随即出现保存文件对话框,从图4-8中,可看到文件名是已经设置好的。主机接收数据时,首先根据数据开头部分判断出是文件数据,再依据图4-6的格式进行解析,具体操作也封装在FileNameHead类中。生成相应的未读类型的消息记录,更新到数据库中。

                                                                                            图4-7 接收文件

                                                                                      图4-8 保存文件对话框

    其中FileNameHead实现的主要代码为:

    class FileNameHead{

            public static byte[] GetBytes(string FileName){

                byte[] fileNameByte = Encoding.Unicode.GetBytes(FileName);

                byte[] fileNameLengthForVauleByte = Encoding.Unicode.GetBytes(fileNameByte.Length.ToString());

                byte[] fileAttributeByte = new byte[fileNameByte.Length + fileNameLengthForVauleByte.Length];

                fileNameLengthForVauleByte.CopyTo(fileAttributeByte,0);

               fileNameByte.CopyTo(fileAttributeByte,fileNameLengthForVauleByte.Length);

                return fileAttributeByte;

            }

            public static int GetFileNameByteLength(byte[] FileNameHeadByte){

                byte[] fileNameLengthForVauleByte = new byte[4];

                Array.Copy(FileNameHeadByte, 8, fileNameLengthForVauleByte,0,4);

                string FileNameByteLength = Encoding.Unicode.GetString(fileNameLengthForVauleByte);

                int FileNameByteLengthNum = Convert.ToInt32(FileNameByteLength);

                return FileNameByteLengthNum;

            }

            public static string GetFileName(byte[] FileNameHeadByte, int FileNameByteLength){

                byte[] fileNameBytes = new byte[FileNameByteLength];

                Array.Copy(FileNameHeadByte, 12, fileNameBytes, 0, FileNameByteLength);

                string FileName = Encoding.Unicode.GetString(fileNameBytes);

                return FileName;

            }

        }

    4.5截图模块

    截图模块中的连接部分与文字聊天的相同,截图完成后,保存为图片文件,传输方式与文件传输模块的相同。因此接下来将着重介绍截图功能。

    点击用户,然后点击聊天控件中的发送文件按钮。启动名字为ScreenCut的WinFrom窗口。在窗体的加载事件中,通过调用Graphics类的CopyFromScreen方法获取到电脑屏幕的截图,并设置为窗体的背景图像和原图,然后出现相应的提示。如图4-9

                                                                                      图4-9 截图提示

    在ScreenCut窗口的后台代码中,主要监听鼠标的点击事件。需要监听的鼠标点击事件主要分为三个:

    1、鼠标按鈕已按下的事件

    当鼠标第一次点击时,判断是鼠标右键还是左键:右键则关闭当前窗口退出截图。左键,则判断,图片有没有出现用于截取部分图片的红色边框,有就记录鼠标位置,没有就记录鼠标下落的点,同时设置Rectangle类变量Rect的X、Y的值。

    2、鼠标移动事件。

    当鼠标移动时,判断图片有没有出现用于截取区域的红色边框。如果有边框,而且鼠标左键处于点击状态,比较上次位置的鼠标位置,计算偏移量,使用Graphics类的DrawRectangle方法,在原图的基础上重新绘制红色边框,并将新绘制的图片显示在窗口中。因为不断刷新重新绘制的原因,所以用户在使用时,感受不到卡顿,直观上会以为红色边框在随鼠标移动。如果没有出现过红色边框,但鼠标左键处于点击状态。同样需要不断绘制边框,但需要考虑鼠标目前所在的点,与左键下落的点之间的位置关系,从而设置变量Rect的宽度和高度。截图效果如图4-10

    3、鼠标双击事件。

    只需要对一种情况进行处理。如果是鼠标左键点击,并且是在红色边框内点击的,则使用Graphics类的CopyFromScreen方法截取对应部分区域的图片。然后将图片保存在系统程序所在的目录下的pic文件夹中(若不存在,将被创建),图片的文件名将以DateTime.Now.ToFileTime().ToString()的返回值命名。返回值是当前时间的长整型数字,这个数字是由年精准到微秒的。最后启动SendPic窗口,关闭当前窗口。

                                                                                     图4-10 截图效果展示

    在SendPic窗口,显示刚刚截取的图片,具体效果图如图4-11。若点击“发送”按钮。将调用自定义的ClassSendPic类发送图片,同时生成相应已读类型的记录更新到数据库,同时也将信息添加到显示信息的ListView中。接收信息的客户端,将生成标记为未读信息的记录插入到数据库中。

                                                                                图4-11 发送图片窗口展示

    4.6录音模块

    录音模块的非关键部分与之前模块的相似,包括建立连接和传输方式。接下来具体介绍录音功能的实现。

    在聊天控件中,点击录音按钮,将启动名为Recording的窗口,如图4-12。在窗体的加载事件中,初始化录音设备并开始录音,即窗体一启动,系统就开始录制语音。

    在窗体的后台代码中,使用DllImport导入winmm.dll中的mciSendString方法。之后的录音操作都设计到此方法。

                                                                                        图4-12 录音界面

    点击发送按钮,停止录音,并将已录制的语言信息保存为WAV文件。文件将保存在系统程序所在的目录下的rec文件夹中(若不存在,将被创建),文件名的命名方式与截图的命名方式相同。随后实例化ClassSendReco类,新建一个线程执行ClassSendReco类的SendReco方法,传输语言信息。

    点击取消按钮,系统将停止录音并关闭录音界面,不保存录制的语音文件。

    4.7历史记录模块

    历史记录模块的功能是将历史记录保存在本地,在本系统下次启动时后还能显示出来,用户也可以清空历史记录.在系统启动时,会检查是否存在数据库和表,若没有则创建。考虑系统的应用环境和项目要求,所以数据库采用嵌入式数据库SQLite。同时,本功能模块主要的部分是数据库的设计以及对数据库的操作。

    ​​​​​​​4.7.1数据库设计

    根据软件需求分析。为了良好、有效地记录历史信息,设计了一个包含2个表的数据库,分别为:

    用户昵称表:放置了2个属性,分别为(MAC地址,用户昵称)。

    聊天信息表:放置了7个属性,分别为(信息号,MAC地址,发言人,消息类型,消息内容,是否读过,消息时间)

    1. 用户昵称表

                                                                               表1 Nick表

    字段名称

    数据类型

    是否允许为空

    主键

    描述

    MacAdd

    varchar(40)

    通信网卡的物理地址

    Nickname

    varchar(40)

    -

    用户昵称

     

    1. 聊天信息表

                                                                                表1 Detail表

    字段名称

    数据类型

    是否允许为空

    主键

    描述

    Did

    INTEGER

    用来标记的ID,设置为自动增长

    Dmac

    varchar(40)

    -

    物理地址

    Dspeak

    varchar(30)

    -

    发言人

    Dtype

    INTEGER

    -

    消息类型

    Dcont

    varchar(150)

    -

    信息的内容,根据Dread的值而不一样

    Dread

    INTEGER

    -

    是否读过的标识

    Ddatetime

    datetime

    -

    默认设置为插入信息的时间

     

                                                                                图4-13 Detail表数据库显示

    4.7.2​​​​​​​各种类型信息的记录

    每一条插入到数据库Detail表的数据都具有以下7个:

    Did:每条信息的ID号,用于标记,设置为从1开始自动增长。

    Dmac:用于区分消息,表示这条消息是与网卡MAC地址为Dmac的主机的通信过程中产生的。

    Dspeak:记录在这次通信中,这条信息是哪个主机发送的。

    Dtype:用数字类型记录信息类型,0表示文本信息,1表示文件信息,2表示截图的图片信息,3表示录制的语音信息

    Dcont:根据Dtype的值而不同,Dtype为0时,存储文本信息内容,Dtype为1、2或3时,存储文件、截图或音频的文件路径

    Dread:用数字类型标记这条消息是否读过,0表示未读,1表示已读

    Ddatetime:设置时间默认为插入这条信息的时间

    ​​​​​​​4.7.3历史消息的显示界面

    点击用户,然后点击“历史记录”按钮,将启动一个新窗口显示与这个用户的聊天记录,具体显示效果,如图4-13. 窗口中有个ListView用于显示。点击“清空”按钮,将调用自定义的DetailDAL类中的DeleteOne方法,删除与当前用户的所有聊天记录。

                                                                                图4-14 历史消息记录的显示

     

    在消息记录的显示界面中,点击ListView的子项。若是文件信息,将打开文件所在的文件夹。若是截图的图片信息,将打开一个DisplayPic的WinForm窗口用于显示图片。若是语音信息,则使用MediaElement控件播放音频文件。如图4-14.聊天界面中,信息显示的ListView同样具有这样的功能。

                                                                                    图4-15 点击截图显示

     

    5.总结和展望

     

    5.1总结

    在此次毕业设计中,我使用了C#语言和VS2012开发工具开发了一个基于WINJDOWS平台的局域网即时通讯工具。该系统在提高网络资源利用率的同时,实现了文字聊天、文件传输、实时截图和语言发收的功能。通过这次实践,大大提高了我的实际动手能力, 同时也锻炼了我的资料查阅搜寻的能力。

    在这次设计中,我充分了解到了C#语言的优秀性能和VS2012在开发方面的高效。同时,我也认识到了学习的重要性。在查阅资料的工程中,从刚开始的盲目看WPF相关书籍,到中期有选择地看C#语言书籍和C#开发范例书籍,再到后期针对性地在收集资料。在实际实现的过程中,最初盲目觉得功能简单,同时高估了自己的能力,计划短时间内实现,导致未完成最初的计划安排。后来,通过反思,开始尝试逐步实现各个功能,并对每一项功能键都进行一个详细的过程安排。文字聊天中的发送端发送信息大致分成五步实现。这次毕业设计,不仅使我感受到了自己的不足,也是我具有初步的系统开发能力。

    5.2展望

    由于时间的仓促,同时也受限于个人的开发能力,本系统还存在一些技术上的问题,在今后的学习实践中,还可以进行不断的修改和完善。可改进的方面大致可以分为五。

    1、主界面与聊天界面的分离。由于功能是逐步实现的,在实现文字聊天功能时,没有历史记录功能,同时Socket绑定监听的原因,导致主界面与聊天界面在同一窗口中。最直接的结果是用户不能同时和多个用户聊天。

    2、文件传输进度的显示。在传输大文件时,用户不确定文件的传输进度,由此可能会产生不可预知的情况。

    3、截图的改善。在截取图片时不够直观,图片的质量也不高。

    4、音频的质量。因为使用WINDOWS API函数的原因,录取的音频质量不高,带有一定的噪音。

    5、添加新功能,包括但不限于语言通话、视频通话等。

     

    参考文献

    1. 宋嘉程.即时通讯软件应用研究[J]. 山东青年, 2017,8:8-9,13.
    2. Hans John Nielsen. Library communication outside a library context: instant messaging as library service [J]. New Library World, 2009, 110(5/6).
    3. Carol X.J.Ou, Robert M.Davison, Xuepan Zhong, Yi Liang. Empowering employees through instant messaging [J]. Information Technology & People2010, 23(2).
    4. 陆伟,林培榕,林姿琼. 企业即时通讯系统设计[J].软件导刊, 2015,10:94-96.
    5. 雷东升.网络即时通讯系统[J].计算机与现代化, 2008,4:51-53.
    6. 花鹏.分析即时通讯工具现状及发展方向[J].探索科学, 2016,5:49.
    7. 柳烨,谭敬德.QQ 即时通讯工具在大学生课程学习中的需求分析[J].湖南第一师范学院学报,2014,04:80-84.
    8. 于峰海. 面向再制造的工程机械创新设计研究[D].陕西科技大学,2014.
    9. 张晗雨.WPF全视角分析[M].北京:机械工业出版社,2008.12.
    10. 李红.基于C/S模式的SOCKET网络编程分析[J].现代商贸工业, 2009,9:259-260.
    11. 张晓明.C#网络通信程序设计[M].北京:清华大学出版社,2015.
    12. 吴艳平. C#多线程编程[J].电脑迷, 2017,15:92.
    13. 严谦,阳泳. 网络编程TCP/IP协议与socket论述[J].电子世界, 2016,8:68-68,70.
    14. 李红.基于C/S模式的SOCKET网络编程分析[J].现代商贸工业, 2009,9:259-260.
    15. Christian Nagel.C#高级编程:C# 6 &.NET CORE 1.0[M]. 北京:清华大学出版社, 2017.4
    展开全文
  • C# 局域网通信

    2020-07-26 23:33:03
    C# WPF 实现局域网通讯,文件发送,图片发送
  • c#局域网聊天,可以参考一下,还有点错误的,基本功能已经实现。c#局域网聊天,可以参考一下,还有点错误的,基本功能已经实现。c#局域网聊天,可以参考一下,还有点错误的,基本功能已经实现。c#局域网聊天,可以...
  • C#局域网聊天源码

    2020-07-30 23:31:13
    C#局域网聊天源码,vs2013测试通过,代码写的很好指的参考
  • 这是用C#开发的电脑屏幕监控系统,可以实现同时监控多台电脑,限于同一个局域网内,如果是要同时监控多台电脑,需要SQL server的支持,分为客户端和服务端(使用时需要改动一下客户端里面的连接ip地址,改为服务端...
  • C#获取局域网内在线主机ip,发送和接收数据。
  • 我将网上的C#语音和视频结合并加以优化了一下,已经将其用在商业软件中的一个部分,供大家参考
  • 这个是本人学习c#网络编程时写的,采用服务端的方式多人聊天工具,用户之间通过服务器转发来通信,服务端可以给客户端发送文本、文件、抖窗,欢迎初学者下载学习!
  • 一个基于c#的点对点局域网文件传输小案例,运行效果截图 //界面窗体 using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.IO;...

     

    一个基于c#的点对点局域网文件传输小案例,运行效果截图

    //界面窗体

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;

    namespace 文件传输
    {
    public partial class Form1 : Form
    {
    /// <summary>
    /// 文件名
    /// </summary>
    private string fileName;
    /// <summary>
    /// 文件路径
    /// </summary>
    private string filePath;
    /// <summary>
    /// 文件大小
    /// </summary>
    private long fileSize;
    public Form1()
    {
    InitializeComponent();
    Thread.CurrentThread.IsBackground=true;
    textBox2.Text = IpUtil.GetLocalIp();
    label1.Text = "您的ip:" + IpUtil.GetLocalIp() + " 您的端口:" + IpUtil.GetRandomPort();
    var s= new FileRecive(this);
    new Thread(s.run).Start();
    }

    /// <summary>
    /// 信息提示框
    /// </summary>
    /// <param name="msg"></param>
    public void Tip(string msg) {

    MessageBox.Show(msg,"温馨提示");
    }

    /// <summary>
    /// 发送文件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void button2_Click(object sender, EventArgs e)
    {
    string ip = textBox2.Text;
    string port =textBox3.Text;

    if (fileName.Length == 0) {

    Tip("请选择文件");
    return;
    }
    if(ip.Length==0||port.ToString().Length==0){

    Tip("端口和ip地址是必须的!");
    return;
    }

    var c = new FileSend(this,new string[]{ip,port,fileName,filePath,fileSize.ToString()});
    new Thread(c.Send).Start();
    }

    /// <summary>
    /// 选择文件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void button1_Click(object sender, EventArgs e)
    {
    OpenFileDialog dig = new OpenFileDialog();

    dig.ShowDialog();

    //获取文件名
    this.fileName = dig.SafeFileName;

    //获取文件路径
    this.filePath = dig.FileName;

    FileInfo f = new FileInfo(this.filePath);

    //获取文件大小
    this.fileSize = f.Length;
    textBox1.Text = filePath;
    }

    /// <summary>
    /// 更新进度条
    /// </summary>
    /// <param name="value"></param>
    public void UpDateProgress(int value) {


    this.progressBar1.Value=value;
    this.label2.Text = value + "%";
    System.Windows.Forms.Application.DoEvents();
    }

    /// <summary>
    /// 修改状态
    /// </summary>
    /// <param name="state"></param>
    public void SetState(string state) {

    label5.Text = state;
    }
    /// <summary>
    /// 退出程序
    /// </summary>
    public void Exit() {

    Application.Exit();
    }
    }
    }

    //ip和端口工具类

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

    namespace 文件传输
    {
    class IpUtil
    {
    /// <summary>
    /// 获取本地ip地址
    /// </summary>
    /// <returns></returns>
    public static string GetLocalIp()
    {
    string hostname = Dns.GetHostName();
    IPHostEntry localhost = Dns.GetHostByName(hostname);
    IPAddress localaddr = localhost.AddressList[0];
    return localaddr.ToString();
    }

    /// <summary>
    /// 产生随机端口
    /// </summary>
    /// <returns></returns>
    public static int GetRandomPort() {


    return new Random().Next(1000)+5000;
    }
    }
    }

    //文件发送类

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

    namespace 文件传输
    {

    //文件发送类
    class FileSend
    {
    private TcpClient client;
    private NetworkStream stream;
    private string[] param;
    private Form1 fm;
    public FileSend(Form1 fm,params string[] param) {

    this.param = param;
    this.fm = fm;

    }

    public void Send()
    {

    try
    {
    //连接接收端
    this.client = new TcpClient(param[0], int.Parse(param[1]));
    string msg = param[2] + "|" + param[4];
    byte[] m = Encoding.UTF8.GetBytes(msg);

    while (true){
    this.stream = this.client.GetStream();
    this.stream.Write(m, 0, m.Length);
    this.stream.Flush();
    byte[] data = new byte[1024];
    int len = this.stream.Read(data, 0, data.Length);
    msg = Encoding.UTF8.GetString(data, 0, len);
    //对方要接收我发送的文件
    if (msg.Equals("1"))
    {

    fm.SetState("正在发送:");
    FileStream os = new FileStream(param[3], FileMode.OpenOrCreate);

    data = new byte[1024];
    //记录当前发送进度
    long currentprogress = 0;
    len=0;
    while ((len = os.Read(data, 0, data.Length)) > 0) {
    currentprogress += len;
    //更新进度条
    fm.UpDateProgress((int)(currentprogress*100/long.Parse(param[4])));
    this.stream.Write(data,0,len);

    }
    os.Flush();
    this.stream.Flush();
    os.Close();
    this.stream.Close();
    fm.Tip("发送成功!");
    fm.Exit();
    }
    }
    }
    catch (Exception e)
    {

    fm.Tip(e.Message);

    }

    }
    }
    }

     

    //文件接收类

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

    namespace 文件传输
    {

    /// <summary>
    /// 文件接收类
    /// </summary>
    class FileRecive
    {

    private TcpListener server;
    private Form1 fm;
    private NetworkStream stream;
    public FileRecive(Form1 fm) {
    this.fm = fm;
    try
    {
    this.server = new TcpListener(IPAddress.Parse(IpUtil.GetLocalIp()), IpUtil.GetRandomPort());

    server.Start();
    }
    catch (Exception e) {

    fm.Tip(e.Message);

    }
    }

    /// <summary>
    /// 接收文件
    /// </summary>
    public void run()
    {


    while (true)
    {
    try
    {
    TcpClient client = server.AcceptTcpClient();
    this.stream = client.GetStream();
    byte[] msgs = new byte[1024];

    int len = this.stream.Read(msgs, 0, msgs.Length);

    string msg = Encoding.UTF8.GetString(msgs, 0, len);

    string[] tip = msg.Split('|');
    if (DialogResult.Yes == MessageBox.Show(IpUtil.GetLocalIp() + "给您发了一个文件:" + tip[0] + "大小为:" + (long.Parse(tip[1]) / 1024) + "kb ,确定要接收吗?", "接收提醒", MessageBoxButtons.YesNo))
    {

    //将接收信息反馈给发送方
    msg = "1";
    msgs = Encoding.UTF8.GetBytes(msg);
    this.stream.Write(msgs, 0, msgs.Length);
    this.stream.Flush();
    fm.SetState("正在接收:");
    //开始接收文件
    string path = @"C:\Users\Administrator\Desktop\" + tip[0];//接收文件的存储路径
    FileStream os = new FileStream(path, FileMode.OpenOrCreate);

    byte[] data = new byte[1024];
    long currentprogress = 0;
    int length = 0;
    while ((length = this.stream.Read(data, 0, data.Length)) > 0)
    {
    currentprogress += length;
    //更新进度条
    fm.UpDateProgress((int)(currentprogress * 100 / long.Parse(tip[1])));
    os.Write(data, 0, length);

    }
    os.Flush();
    this.stream.Flush();
    os.Close();
    this.stream.Close();
    fm.Tip("成功接收文件并存入了" + path + "中!");
    fm.Exit();

    }

    }
    catch (Exception e)
    {
    fm.Tip(e.Message);

    }
    }
    }
    }
    }

     

    转载于:https://www.cnblogs.com/zzjbk/p/5384911.html

    展开全文
  • 小白作品,大神见笑
  • c#局域网共享搜索工具(含源码)

    热门讨论 2020-07-29 14:19:14
    局域网共享搜索的工具,适合在公司内部局域网使用,因为要遍历各个文件,所以速度太慢,不过软件实现了一些有趣的功能,希望能给你带来方便。 <br>功能: 1. 文件搜索,分为按目录搜和按文件搜两种。 2. ...
  • C#局域网文件传输

    2020-05-05 23:30:34
    C#局域网 文 件 传 输 ,是一个很好的学习文档,帮助你提高自己的开发水平
  • 包括Server端和Client端,实现远程监控电脑屏幕
  • 基​于​C​#​局​域​网​语​音​聊​天​室​,​可​实​现​文​本​消​息​的​发​送​、​接​收​及​语​音​聊​天​,​是​一​个​很​不​错​的​,​适​合​初​学​者​的​软​件​开​发​项​...
  • c# 局域网聊天 仿飞秋和飞鸽传书

    热门讨论 2020-07-30 23:32:34
    c# 实现的局域网聊天软件,可发送表情,文件。 1.参照网上若干局域网聊天软件编写而成。 2.发送消息使用UDP,传送文件使用TCP 3.用户上线时,自动发送广播消息,而后在双方好友列表里可以互相看见 4.支持更改用户名 ...
  • C#局域网实时聊天

    2019-09-06 16:56:34
    本程序可以使用ip也可以使用主机名,这样就可以在打包之后,就不需要一直动态修改IP了 服务器端代码: public partial class FServer : Form { public FServer() ... TextBox.CheckForIl...
  • 这是我自己闲的时候做的,有兴趣的朋友可以去看看
  • C# 局域网语音通讯(Winform)

    热门讨论 2020-07-30 23:32:14
    该资源为国外开源的一款局域网C#语音通讯工具,简单方便(使用VS2010打开)。本人已经运行测试可以行。使用Winform开发,可以使用笔记本麦克风与喇叭一起使用(保证在同一网段下)。
1 2 3 4 5 ... 20
收藏数 11,487
精华内容 4,594
关键字:

c#局域网