利用socket以及多线程、文件流等方法实现通信,互发文本信息以及文件
服务器端:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
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 通讯程序再写一次
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Socket socketListen;
private void btnListen_Click(object sender, EventArgs e)
{
try
{
//创建监听socket
socketListen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//获取ip
IPAddress ip = IPAddress.Parse(txtIP.Text);
//获取端口号
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPoint.Text));
//将负责监听的socket绑定这个端口号
socketListen.Bind(point);
ShowMsg("开始监听!");
//设置监听队列,就是在同一时间允许连接的端口数量
socketListen.Listen(10);
//创建一个新线程来执行这个一直在监听中的方法
Thread th = new Thread(Listen);
th.IsBackground = true;
th.Start();
}
catch { }; }
/// <summary>
/// 调用这个方法时把相关内容打印到文本框中
/// </summary>
/// <param name="str"></param>
void ShowMsg(string str)
{
txtRecive.AppendText(str + "\r\n");
}
//创建一个dictionary集合用来存储连入的端口号,以ip名为键,socket为值
Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();
void Listen()
{
while (true)
{
try
{
//负责监听的socket在接收到客户端的连接之后 创建一个负责通信的socket来接收
socketSend = socketListen.Accept();
//如果接收成功 就把发送端的地址显现出来
ShowMsg(socketSend.RemoteEndPoint.ToString() + "连接成功!");
dicSocket.Add(socketSend.RemoteEndPoint.ToString(), socketSend);
//将连入的ip加入listbox里面
pointList.Items.Add(socketSend.RemoteEndPoint.ToString());
//一直接收客户端发来的信息
//需要开启一个新线程
Thread th = new Thread(Recive);
th.IsBackground = true;
th.Start();
}
catch { };
}
}
Socket socketSend;
/// <summary>
/// 接收客户端发来的信息
/// </summary>
void Recive()
{
while (true)
{
try
{
byte[] buffer = new byte[1024 * 1024 * 5];
int r = socketSend.Receive(buffer);
if (r == 0)
{
break;
}
string reciveTxt = Encoding.UTF8.GetString(buffer, 0, r);
ShowMsg(socketSend.RemoteEndPoint + ":" + reciveTxt);
}
catch
{
MessageBox.Show("对方关闭了连接");
break;
}
}
} private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
}
/// <summary>
/// 发送文本框中的信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSend_Click(object sender, EventArgs e)
{ string str = txtSend.Text;
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
//创建一个list泛型集合装进buffer数组,这样可以在字节前面加个我们规定的协议
//比如说这里0为发送文本消息,1为发送文件
List<byte> list = new List<byte>();
//首先这里先把0添加进去,放在第一位,发过去之后再由接收端判断是什么文件,那边再解析
list.Add(0);
list.AddRange(buffer);
//再把集合转化成字节数组,list集合里装的是什么类型的数组,那返回的就是什么类型的数组
byte[] newBuffer = list.ToArray(); //得到listbox里面选中的ip作为键,在dictionary里面找出对应的端口号,发送信息
//刚刚试了一下,如果没选的话,返回空,系统抛异常
try
{
string ip = pointList.SelectedItem.ToString();
dicSocket[ip].Send(newBuffer);
}
catch
{
MessageBox.Show("请选择要发送的ip");
}
//socketSend.Send(buffer);
} private void button1_Click(object sender, EventArgs e)
{
//打开选择文件对话框
OpenFileDialog ofd = new OpenFileDialog();
//对话框名字
ofd.Title = "请选择你的文件";
//设定弹出的初始文件夹路径
ofd.InitialDirectory = @"F:\程序测试文件夹";
//设定好要选择的文件类型
ofd.Filter = "所有文件|*.*";
//弹出对话框
ofd.ShowDialog();
//获得文件所选文件的全路径
string path = ofd.FileName;
//把这个全路径先放进文本框里
txtPath.Text = path; } private void btnSendFile_Click(object sender, EventArgs e)
{
//创建一个string类型的路径来存已经选好路径的文本框里的内容
string path = txtPath.Text;
//用文件流来操作文件
using (FileStream fsRead = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Read))
{
//创建字节数组并规定单次接收长度
byte[] buffer = new byte[1024 * 1024 * 5];
//按照规定的方式读取并且接收他的单次实际读取到的长度
int r = fsRead.Read(buffer, 0, buffer.Length);
List<byte> list = new List<byte>();
//同样方法,标记 1,为文件
list.Add(1);
list.AddRange(buffer);
byte[] newBuffer = list.ToArray();
dicSocket[pointList.SelectedItem.ToString()].Send(newBuffer, 0, r + 1,SocketFlags.None); }
}
}
}
客户端:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
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 客户端
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
Socket socketLink;
private void btnLink_Click(object sender, EventArgs e)
{
try
{
socketLink = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Parse(txtIP.Text);
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPoint.Text));
socketLink.Connect(point);
ShowMsg("连接成功!"); Thread th = new Thread(Recive);
th.IsBackground = true;
th.Start();
}
catch { };
}
/// <summary>
/// 传入需要显示在文本框中的内容
/// </summary>
/// <param name="str"></param>
void ShowMsg(string str)
{
txtRecive.AppendText(str + "\r\n");
} void Recive()
{
while (true)
{
try
{
//设定一个字节数组,并规定它的长度
byte[] buffer = new byte[1024 * 1024 * 5];
//接收通过socketLink传过来的字节,存进buffer里,并获取这个字节数组的长度
int r = socketLink.Receive(buffer);
//获取这个字节数组第一位的数字,就是我们规定好的协议,来判断发过来的是消息还是文件
int n = buffer[0];
if (r == 0)
{
break;
}
//如果n==0的话就说明发过来的是文字消息
if (n == 0)
{
string reciveTxt = Encoding.UTF8.GetString(buffer, 1, r - 1);
ShowMsg(socketLink.RemoteEndPoint + ":" + reciveTxt);
}
else if (n == 1)
{
//弹出保存文件的对话框,对接收来的字节数组进行保存
SaveFileDialog sfd = new SaveFileDialog();
sfd.Title = "请选择你要保存的路径";
sfd.InitialDirectory = @"F:\程序测试文件夹";
sfd.Filter = "所有文件|*.*";
//由于版本问题,这里要加this才会弹出保存文件的对话框
sfd.ShowDialog(this);
string path = sfd.FileName;
using (FileStream fsWrite = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
{
fsWrite.Write(buffer, 1, r - 1);
}
ShowMsg("保存成功");
}
}
catch
{
MessageBox.Show("服务器已关闭");
break;
}
}
} /// <summary>
/// 在程序启动时
/// 不让程序报异常:关于子线程持续调用主线程的内容,跳过
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form2_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
}
/// <summary>
/// 点击按钮发送文本框里的信息给socket通讯
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSend_Click(object sender, EventArgs e)
{
string str = txtSend.Text;
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str);
socketLink.Send(buffer);
}
}
}
利用socket以及多线程、文件流等方法实现通信,互发文本信息以及文件的更多相关文章
- C#远程获取图片文件流的方法【很通用】
因为之前写的代码,也能获取到图片流信息,但是会是凌乱的线条,后百度得这个方法,必须记录一下 C# try { WebRequest myrequest = WebRequest.Create(Http ...
- C#文件流写入方法
stream为服务端接收的文件流 var bytes = new byte[stream.Length]; stream.Read(bytes, 0, bytes.Length); // 设置当前流的 ...
- 根据上传的MultipartFile通过springboot转化为File类型并调用通过File文件流的方法上传特定服务器
@PostMapping("uploadExcel") public ResponseObj uploadExcel(@RequestParam("excelFile ...
- web api 如何通过接收文件流的方式,接收客户端及前端上传的文件
服务端接收文件流代码: public async Task<HttpResponseMessage> ReceiveFileByStream() { var stream = HttpCo ...
- android中利用Socket实现手机客户端与PC端进行通信
1. 项目截图
- Filezilla FTP Server 设置帐号主目录文件夹的方法和多个帐号共享一个文件夹的方法
1.点击用户头像进入 2.共享文件夹 3.添加共享文件夹 4.设置一个主目录 5.右键主目录 如图6设置别名,别名问主目录路径+别名名称 如:主目录[d:\pro\home\] 别名[aliases1 ...
- 文件寄生——寻找宿主的不归路(NTFS文件流实际应用)
咱们今天来研究下NTFS文件流: NTFS文件系统实现了多文件流特性,NTFS环境一个文件默认使用的是未命名的文件流,同时可创建其他命名的文件流,windows资源管理器默认不显示出文件的命名文件流, ...
- C++文件流类与文件流对象
文件流是以外存文件为输入输出对象的数据流.输出文件流是从内存流向外存文件的数据,输入文件流是从外存文件流向内存的数据.每一个文件流都有一个内存缓冲区与之对应. 请区分文件流与文件的概念,不用误以为文件 ...
- C# IO操作(四)大文件拷贝(文件流的使用)、文件编码
大文件拷贝(文件流的使用).文件编码 首先说一下大文件拷贝和文件流,因为计算机的内存资源是有限的,面对几个G甚至更大的文件,需要通过程序来完成拷贝,就需要用到文件流(因为我们无法做到把文件一 ...
- .net 流(Stream) - 文件流、内存流、网络流
转自:http://www.oseye.net/user/kevin/blog/85 一.文件流 FileStream FileStream流继承与Stream类,一个FileStream类的实例实际 ...
随机推荐
- Java基础之常用类(String类)
String 类 定义 String 类代表字符串.Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现.我们可以将字符串看作是String, 但是严格意义上 ...
- [深度学习] ImageAI库使用笔记
ImageAI是一个Python库,旨在使开发人员,研究人员和学生能够使用简单的几行代码来构建具有独立的深度学习和计算机视觉功能的应用程序和系统. ImageAI的官方GitHub存储库为https: ...
- ESXI 7.0封装网卡驱动
前段时间配置的All In One 主机,由于华擎H410M-ITX/AC主板的板载网卡为intel I219-V,在安装ESXI后网卡无法驱动.查询之后发现原来ESXI7.0.2的版本不含该网卡驱动 ...
- .NET周报【1月第3期 2023-01-20】
这应该是2023年农历新年前的最后一篇.NET周报,再次预祝大家新年快乐! 国内文章 看我是如何用C#编写一个小于8KB的贪吃蛇游戏的 https://www.cnblogs.com/InCerry/ ...
- 字符串拼接输出-Predicate接口
字符串拼接输出 下面的字符串数组当中存有多条信息,请按照格式""\姓名∶XX.性别:xx."的格式将信息打印出来.要求将打印姓名的动作作为第一个Consumer 接口的L ...
- Spring Boot + WebSocket 实时监控异常
本文已经收录到Github仓库,该仓库包含计算机基础.Java基础.多线程.JVM.数据库.Redis.Spring.Mybatis.SpringMVC.SpringBoot.分布式.微服务.设计模式 ...
- CH32芯片_EVT工程配置方法说明
CH32V系列 注意: 我们EVT例程中默认配置是CH32V203C8T6配置,若使用MCU为CH32V203K8T6-CH32V203C8U6-CH32V203C8T6,无需修改配置 若使用MCU为 ...
- 12月14日内容总结——模板层之标签、自定义模板语法、母版(模版)的继承与导入、模型层前期准备知识点、ORM常用关键字
目录 一.模板层之标签 分支结构if for循环 with(定义变量名) 二.自定义过滤器.标签及inclusion_tag(了解) 三.母版(模板)的继承与导入(重要) 四.模型层之前期准备 模型层 ...
- mysql15 sql优化-小表驱动大表 IN和EXITS
转:https://blog.csdn.net/qq_27409289/article/details/85963089 1.IN查询分析 select * from a where a.id in ...
- 亲测有效! Scrutiny 网站SEO检测及优化工具 V12.6.1 for mac
亲测有效! Scrutiny 网站SEO检测及优化工具 V12.6.1 for mac Scrutiny是一款网站SEO工具,它能够自动检测目标网站的坏链.HTML验证.描述Description. ...