服务器端:

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以及多线程、文件流等方法实现通信,互发文本信息以及文件的更多相关文章

  1. C#远程获取图片文件流的方法【很通用】

    因为之前写的代码,也能获取到图片流信息,但是会是凌乱的线条,后百度得这个方法,必须记录一下 C# try { WebRequest myrequest = WebRequest.Create(Http ...

  2. C#文件流写入方法

    stream为服务端接收的文件流 var bytes = new byte[stream.Length]; stream.Read(bytes, 0, bytes.Length); // 设置当前流的 ...

  3. 根据上传的MultipartFile通过springboot转化为File类型并调用通过File文件流的方法上传特定服务器

      @PostMapping("uploadExcel") public ResponseObj uploadExcel(@RequestParam("excelFile ...

  4. web api 如何通过接收文件流的方式,接收客户端及前端上传的文件

    服务端接收文件流代码: public async Task<HttpResponseMessage> ReceiveFileByStream() { var stream = HttpCo ...

  5. android中利用Socket实现手机客户端与PC端进行通信

    1. 项目截图

  6. Filezilla FTP Server 设置帐号主目录文件夹的方法和多个帐号共享一个文件夹的方法

    1.点击用户头像进入 2.共享文件夹 3.添加共享文件夹 4.设置一个主目录 5.右键主目录 如图6设置别名,别名问主目录路径+别名名称 如:主目录[d:\pro\home\] 别名[aliases1 ...

  7. 文件寄生——寻找宿主的不归路(NTFS文件流实际应用)

    咱们今天来研究下NTFS文件流: NTFS文件系统实现了多文件流特性,NTFS环境一个文件默认使用的是未命名的文件流,同时可创建其他命名的文件流,windows资源管理器默认不显示出文件的命名文件流, ...

  8. C++文件流类与文件流对象

    文件流是以外存文件为输入输出对象的数据流.输出文件流是从内存流向外存文件的数据,输入文件流是从外存文件流向内存的数据.每一个文件流都有一个内存缓冲区与之对应. 请区分文件流与文件的概念,不用误以为文件 ...

  9. C# IO操作(四)大文件拷贝(文件流的使用)、文件编码

         大文件拷贝(文件流的使用).文件编码 首先说一下大文件拷贝和文件流,因为计算机的内存资源是有限的,面对几个G甚至更大的文件,需要通过程序来完成拷贝,就需要用到文件流(因为我们无法做到把文件一 ...

  10. .net 流(Stream) - 文件流、内存流、网络流

    转自:http://www.oseye.net/user/kevin/blog/85 一.文件流 FileStream FileStream流继承与Stream类,一个FileStream类的实例实际 ...

随机推荐

  1. Ubuntu 22.04 BigSur 美化

    安装 tweaks sudo apt update && sudo apt upgrade sudo apt install gnome-tweaks gnome-shell-exte ...

  2. JS控制台打印星星,总有你要的那一款~呐~给你小心心哦~~~❤

    用JS语句,在控制台中打印星星,你要的是哪一款呢~来认领吧~ 1.左直角星星 效果: 代码: let readline=require("readline-sync"); cons ...

  3. Typora 最后一个免费版本

    介绍 Typora 是一款轻量级的 Markdown 编辑器,其最为出众的特点是: 所见即所得. Typora 于2021年11月23日推出了第一个正式版,并转为收费.不过价格也算合理,89元/3台设 ...

  4. 垃圾收集器必问系列—CMS

    本文已收录至Github,推荐阅读 Java随想录 微信公众号:Java随想录 CSDN: 码农BookSea 应该相信,自己是生活的战胜者.--雨果 目录 CMS简介 运作过程 CMS的缺陷 处理器 ...

  5. java进阶P-2.7

    类函数 函数 用于按指定字符(串)或正则去分割某个字符串,结果以字符串数组形式返回:对某些特殊字符,如果字符(串)正好是正则的一部分,则需要转义才能使用 字符有 | , + , * , ^ , $ , ...

  6. RocketMQ Streams 1.1.0: 轻量级流处理再出发

    本文作者:倪泽,Apache RocketMQ committer.RSQLDB/RocketMQ Streams Maintainer 01 背景 RocketMQ Streams是一款基于Rock ...

  7. Vue+Element-Ui设置收货地址,省市区三级联动,详细地址信息调用腾讯地图关键词输入提示api

    省市区三级联动的数据 我这里找了一个json格式的数据,直接放在前端项目的文件夹下,这里粘贴出来 pca.json文件内容 { "北京市": { "市辖区": ...

  8. 9月21日内容总结——计算机基础知识、typora软件的安装与软件内的部分markdown语法

    今日内容总结 目录 今日内容总结 一.路径 1.绝对路径 2.相对路径 二.计算机的本质 三.计算机的五大组成部分 1.控制器 2.运算器 PS:CPU=控制器+运算器 3.存储设备 4.输入设备 5 ...

  9. Python3中的“加和”函数

    技术背景 其实如果没有专门去研究python的一些内置函数的话,我们都没办法发现一些很神奇的功能,即使是我们最熟悉的python中的sum函数.不知道还有多少人,以为这只是一个只能用来做求和的函数? ...

  10. 深度优先搜索算法-dfs讲解

    迷宫问题 有一个迷宫: S**. .... ***T (其中字符S表示起点,字符T表示终点,字符*表示墙壁,字符.表示平地.你需要从S出发走到T,每次只能向上下左右相邻的位置移动,不能走出地图,也不能 ...