前言
最近在学习C# Socket相关的知识,学习之余,动手做了一个简单的局域网聊天器。有萌生做这个的想法,主要是由于之前家里两台电脑之间想要传输文件十分麻烦,需要借助QQ,微信或者其他第三方应用,基本都要登录,而且可能传输的文件还有大小限制,压缩问题。所以本聊天器的首要目标就是解决这两个问题,做到使用方便(双击启动即用),传文件无限制。
废话不多说,先上图。S-Chat是服务端,C-Chat是客户端,两者除了客户端首次启动后需要设置一下连接的IP地址外,无其他区别。操作与界面都完全相同,对于用户来说,基本不用在意谁是服务端谁是客户端。

编码
服务端监听接口
服务端主要负责开启监听线程,等待客户端接入

public void StartListen()
{// 创建Socket对象 new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)Socket socket = GetSocket();// 将套接字与IPEndPoint绑定socket.Bind(this.GetIPEndPoint());// 开启监听 仅支持一个连接socket.Listen(1);// 开启线程等待客户端接入,避免堵塞Thread acceptThread = new Thread(new ThreadStart(TryAccept));acceptThread.IsBackground = true;acceptThread.Start();
}public void TryAccept()
{Socket socket = GetSocket();while (true){try{Socket connectedSocket = socket.Accept()this.ConnectedSocket = connectedSocket;OnConnect();  // 连接成功回调this.StartReceive();  // 开始接收线程break;}catch (Exception e){}}
}

客户端连接接口
客户端主要负责开启连接线程,每隔2秒,自动尝试连接服务端

public void StartConnect()
{Thread connectThread = new Thread(new ThreadStart(TryConnect));connectThread.IsBackground = true;connectThread.Start();
}public void TryConnect()
{Socket socket = GetSocket();while (true){try{socket.Connect(this.GetIPEndPoint());this.ConnectedSocket = socket;OnConnect();  // 连接成功回调this.StartReceive();break;}catch (Exception e){Thread.Sleep(TryConnectInterval);  // 指定间隔后重新尝试连接}}
}

文字发送,文件发送,接收文字,接收文件等通用接口主要实现在ChatBase类中,是服务端与客户端的共同父类。

文字发送接口
发送数据的第一位表示发送信息的类型,0表示字符串文字,1表示文件
然后获取待发送字符串的长度,使用long类型表示,占用8个字节
共发送的字节数据可以表示为头部(类型 + 字符串字节长度,共9个字节)+ 实际字符串字节数据

public bool Send(string msg)
{if (ConnectedSocket != null && ConnectedSocket.Connected){byte[] buffer = UTF8.GetBytes(msg);  byte[] len = BitConverter.GetBytes((long)buffer.Length);  byte[] content = new byte[1 + len.Length + buffer.Length];  content[0] = (byte)ChatType.Str;  // 发送信息类型,字符串Array.Copy(len, 0, content, 1, len.Length);  // 字符串字节长度Array.Copy(buffer, 0, content, 1 + len.Length, buffer.Length);  // 实际字符串字节数据try{ConnectedSocket.Send(content);return true;}catch (Exception e){}}return false;
}

文件发送接口
与字符串发送相同的头部可以表示为(类型 + 文件长度,共9个字节)
还需要再加上待发送的文件名的长度,与文件名字节数据
共发送的字节数据可以表示为头部(类型 + 文件长度,共9个字节)+ 文件名头部(文件名长度 + 文件名字节数据)+ 实际文件数据

public bool SendFile(string path)
{if (ConnectedSocket != null && ConnectedSocket.Connected){try{FileInfo fi = new FileInfo(path);byte[] len = BitConverter.GetBytes(fi.Length);  byte[] name = UTF8.GetBytes(fi.Name); byte[] nameLen = BitConverter.GetBytes(name.Length); byte[] head = new byte[1 + len.Length + nameLen.Length + name.Length];head[0] = (byte)ChatType.File;  // 加上信息发送类型Array.Copy(len, 0, head, 1, len.Length);  // 加上文件长度Array.Copy(nameLen, 0, head, 1 + len.Length, nameLen.Length);  // 加上文件名长度Array.Copy(name, 0, head, 1 + len.Length + nameLen.Length, name.Length);  // 加上文件名字节数据ConnectedSocket.SendFile(path,head,null,TransmitFileOptions.UseDefaultWorkerThread);return true;}catch(Exception e){}}return false;
}

信息接收接口(文字与文件)
主要是解析接收到的字节数据,根据字符串或文件的类型进行处理

public void Receive()
{if (ConnectedSocket != null){while (true){try{// 读取公共头部byte[] head = new byte[9];ConnectedSocket.Receive(head, head.Length, SocketFlags.None);int len = BitConverter.ToInt32(head, 1);if (head[0] == (byte) ChatType.Str){// 接收字符串byte[] buffer = new byte[len];ConnectedSocket.Receive(buffer, len, SocketFlags.None);OnReceive(ChatType.Str, UTF8.GetString(buffer));}else if(head[0] == (byte)ChatType.File){// 接收文件if (!Directory.Exists(dirName)){Directory.CreateDirectory(dirName);}// 读取文件名信息byte[] nameLen = new byte[4];ConnectedSocket.Receive(nameLen, nameLen.Length, SocketFlags.None);byte[] name = new byte[BitConverter.ToInt32(nameLen, 0)];ConnectedSocket.Receive(name, name.Length, SocketFlags.None);string fileName = UTF8.GetString(name);// 读取文件内容并写入int readByte = 0;int count = 0;byte[] buffer = new byte[1024 * 8];string filePath = Path.Combine(dirName, fileName);if (File.Exists(filePath)){File.Delete(filePath);}using (FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write)){while (count != len){int readLength = buffer.Length;if(len - count < readLength){readLength = len - count;}readByte = ConnectedSocket.Receive(buffer, readLength, SocketFlags.None);fs.Write(buffer, 0, readByte);count += readByte;}}OnReceive(ChatType.File, fileName);  }else{// 未知类型}}catch (Exception e){}}}
}

使用
第一次vb.net教程使用,客户java基础端需要python基础教程设置待连接的IP地址。之后再启动会自动连接

双击服务端exe启动,点击设置,查看IP地址项

双击客户端exe启动,点击设置,在IP地址项,输入服务端查看到的IP地址

设置成功后,等待大约一两秒,应用c#教程cion变成绿色,即表示连接成功,可以正常发送sql语句文字和文件了

可以点击选择文件(支持选择多个文件),发送文件

支持直接拖拽文件到输入框,发送文件

支持Ctrl+Enter快捷键发送

接收到的文件自动存放在exe所在目录的ChatFiles文件夹下

注意事项
客户端服务端需要在同一个局域网下才能实现连接
服务端IP地址是不支持修改的,自动读取本机的IP地址
源码
完整代码放在GitHub上,点击查看
预编译好的可运行exe程序,在仓库的Release目录,也可以直接通过百度云下载,提取码v4pe
作者:iwiniwin
出处:http://www.cnblogs.com/iwiniwin/

C# Socket编程实现简单的局域网聊天器相关推荐

  1. java网络编程,通过TCP,Socket实现多对一的局域网聊天室

    java网络编程,通过TCP,Socket实现多对一的局域网聊天室 可以实现多个客户端连接服务器,服务器接收到信息就会把信息广播到所有的客户端 这是服务器端的代码 View Code import j ...

  2. python socket编程 实现简单p2p聊天程序

    转载自:https://www.cnblogs.com/wuxie1989/p/7204887.html python socket编程 实现简单p2p聊天程序 目标是写一个python的p2p聊天的 ...

  3. Qt学习心得之网络编程简单的局域网聊天服务端建立

    学而不思则罔,思而不学则殆.学习和思考是相辅相成的,通过这几天对网络编程的学习,收获颇丰.接下来我将利用Qt做的一个以TcpIp协议为传输方式的简单的局域网聊天服务端与大家分享下: 首先谈谈我个人对T ...

  4. Java网络编程学习——简单模拟在线聊天

    Java网络编程学习--简单模拟在线聊天 学了java网络,也是该做个小案例来巩固一下了. 本次案例将使用UDP和多线程模拟即时聊天,简单练练手. 1.前提知识 需要知道简单的IO流操作,以及简单的U ...

  5. java socket通信 客户端_JavaのSocket编程之简单客户端与服务器端通信

    Socket编程之简单客户端与服务器端通信 socket 通常用来实现客户端和服务端的连接,socket 是Tcp/Ip协议的一个十分流行的编程界面,一个socket 由一个Ip地址和一个端口号唯一确 ...

  6. 基于Python Tkiner、thread与socket实现的简单多人聊天室,在Python中创建TCP服务器与客户端进行通信

    基于Python Tkiner.thread与socket实现的简单多人聊天室,在Python中创建TCP服务器与客户端进行通信 完整代码下载地址:基于Python Tkiner.thread与soc ...

  7. Socket编程之简单介绍 - 蓝天下的雨 - 博客园

    Socket编程之简单介绍 - 蓝天下的雨 - 博客园 Socket编程之简单介绍 - 蓝天下的雨 - 博客园 Socket编程之简单介绍 2013-03-19 15:27 by 蓝天下的雨, 878 ...

  8. 使用nettyio+socket.io搭建简单的网页聊天室

    使用nettyio+socket.io搭建简单的网页聊天室 1 目录结构 2 maven 依赖配置 <project xmlns="http://maven.apache.org/PO ...

  9. Socket编程一实现简易的聊天功能以及文件传输

    干程序是一件枯燥重复的事,每当感到内心浮躁的时候,我就会找小说来看.我从小就喜爱看武侠小说,一直有着武侠梦.从金庸,古龙,梁羽生系列到凤歌(昆仑),孙晓(英雄志)以及萧鼎的(诛仙)让我领略着不一样的江 ...

最新文章

  1. 汇编语言求无符号数组中出现的次数最多数_【今日最佳leecode通俗易懂】无重复字符的最长子串...
  2. VB.Net编程实现Web Service的基础
  3. Tensorflow-gpu 在Anaconda中使用出现问题的解决方式
  4. Redis源码剖析(十一)跳表
  5. Spark之伪分布式搭建、伪分布式Hadoop、Hive安装
  6. linux LyX中文编辑环境安装配置指南-TeX可视化工具
  7. 做一个“多人在线编辑器”,你会怎么开始
  8. [Link]NoSQL
  9. PHP对象和接口抽象类注意事项
  10. 使用redis中的watch解决秒杀系统中抢购问题
  11. 计算机专业就业方向总结(选择也许更重要)
  12. 面试技巧:HR常问的70个问题回答技巧
  13. 自我介绍html模板王,小学生个人自我介绍模板10篇
  14. VMware SDS之11: VMware SPBM之DELL SC(也即Compellent)篇
  15. Ubuntu 22.04.1 配置 LXR 阅读Linux kernel源码
  16. 拼多多开店怎么做推广?四川万顿思
  17. Python中getA() 的意思
  18. 给小白分享几个学习Android的网站
  19. compact php,php compact 通过变量创建数组
  20. 【Python爬虫实战】用urllib与服务端交互(发送和接收数据)

热门文章

  1. Mac 10.12安装截图工具Jietu
  2. iOS开发中多线程的那些事
  3. Linux管道的容量大小及管道的数据结构
  4. Linux【学习心得】深入剖析软件的源码安装
  5. 自己作为CA签署SSL证书
  6. maven插件学习(maven-shade-plugin和maven-antrun-plugin插件)
  7. Installing NetBeans IDE with Fortran compilers
  8. 单片机C51 - 串行通信原理及串口编程实验
  9. 软件测试方法汇总 - 从不同角度分析软件测试方法有哪些
  10. 校园网连接成功但是无法打开登录界面解决方法