利用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类的实例实际 ...
随机推荐
- 再聊一下那 SQLSERVER 行不能跨页的事
一:背景 1. 讲故事 上一篇写完了之后,马上就有朋友留言对记录行的 8060byte 限制的疑惑,因为他的表记录存储了大量的文章,存储文章的字段类型用的是 nvarchar(max),长度很显然是超 ...
- P8844 [传智杯 #4 初赛] 小卡与落叶
简要题意 给出一个 \(n\) 个节点的以 \(1\) 为根的树,每一个节点 \(i\) 带权 \(w_i\),初始时所有节点的权均为 \(0\).有 \(m\) 个操作,支持以下操作: 1 x,对于 ...
- 【LeetCode链表#9】图解:两两交换链表节点
两两交换链表中的节点 力扣题目链接(opens new window) 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表. 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换. 思路 ...
- 数学 in OI-数论-1
数论 \(1\) \(1.\) 质数 定义就不说了吧. 性质 \(\&\) 定理 质数 \(p\) 有且仅有两个质因子 \(1\) 和 \(p\) . 质数有无穷个. \([1,\, n]\) ...
- 动力节点——day07
什么是异常? 异常是指在程序的运行过程中所发生的不正常的事件,它会中断正在运行的程序 Java中异常的存在形式? 异常在java中以类的形式存在,每一个异常类都可以创建异常对象 异常的继承结构图 编译 ...
- DVWA靶场实战(十一)——XSS(Reflected)
DVWA靶场实战(十一) 十一.XSS(Reflected): 1.漏洞原理: XSS被称为跨站脚本攻击(Cross Site Script),而Reflected被称作反射型XSS.不同于DOM和S ...
- Vue11 vue的data中属性的值(基础数据类型和对象)
1 代码 <body> <div id="root"> <h1>{{name}}</h1> <h1>{{obj}}< ...
- MongoDB数据库记录
启动 MongoDB 服务 标准 URI 连接语法: mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:po ...
- PostgresSQL 常用操作方法
1.后台生成XML作为参数然后数据库解析获取数据 var idList = ids.Split(new string[] { "," }, StringSplitOptions.R ...
- Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation
1.出现问题 查询数据时报如题错误 2.解决方案 建表时需指定字符集,例如: -- ---------------------------- -- Table structure for testTa ...