利用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); } } }