目录
预备知识
视频教程
项目前准备知识点
1、服务器端程序的编写步骤
2、客户端程序编写步骤
代码部分
1、服务端FrmServer.cs文件
2、客户端FrmClient.cs文件
3、启动文件Program.cs
结果展示
预备知识
请查阅博客http://t.csdnimg.cn/jE4Tp
视频教程
链接:https://pan.baidu.com/s/13fkwlppoP9aYcXHiFEbKGQ?pwd=cvzn
提取码:cvzn
项目前准备知识点
1、服务器端程序的编写步骤
第一步:调用socket()函数创建一个用于通信的套接字。
第二步:给已经创建的套接字绑定一个端口号,这一般通过设置网络套接口地址和调用bind()函数来实现。
第三步:调用listen()函数使套接字成为一个监听套接字。
第四步:调用accept()函数来接受客户端的连接,这是就可以和客户端通信了。
第五步:处理客户端的连接请求第六步:终止连接。
2、客户端程序编写步骤
第一步:调用socket()函数创建一个用于通信的套接字。
第二步:通过设置套接字地址结构,说明客户端与之通信的服务器的IP地址和端口号。
第三步:调用connect()函数来建立与服务器的连接。
第四步:调用读写函数发送或者接收数据。
第五步:终止连接。
代码部分
1、服务端FrmServer.cs文件
FrmServer.cs窗体
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 SocketTCP
{//声明委托delegate void AddOnLineDelegate(string str, bool bl);//声明委托delegate void RecMsgDelegate(string str);public partial class FrmTCPServer : Form{public FrmTCPServer(){InitializeComponent();myAddOnline = AddOnline;myRcvMsg = RecMsg;myFileSave = FileSave;}//创建套接字Socket sock = null;//创建负责监听客户端连接的线程Thread threadListen = null;//创建URL与Socket的字典集合Dictionary<string, Socket> DicSocket = new Dictionary<string, Socket>();AddOnLineDelegate myAddOnline;RecMsgDelegate myRcvMsg;FileSaveDelegate myFileSave;#region 开始监听/// <summary>/// 开始监听/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_StartServer_Click(object sender, EventArgs e){//创建负责监听的套接字,注意其中参数:IPV4 字节流 TCPsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);IPAddress address = IPAddress.Parse(this.txt_IP.Text.Trim());//根据IPAddress以及端口号创建IPE对象IPEndPoint endpoint = new IPEndPoint(address, int.Parse(this.txt_Port.Text.Trim()));try{sock.Bind(endpoint);Invoke(myRcvMsg, "服务器开启成功!");MessageBox.Show("开启服务成功!", "打开服务");}catch (Exception ex){MessageBox.Show("开启服务失败" + ex.Message, "打开服务");return;}sock.Listen(10);threadListen = new Thread(ListenConnecting);threadListen.IsBackground = true;threadListen.Start();this.btn_StartServer.Enabled = false;}#endregion#region 监听线程/// <summary>/// 监听线程/// </summary>private void ListenConnecting(){while (true){//一旦监听到一个客户端的连接,将会创建一个与该客户端连接的套接字Socket sockClient = sock.Accept();string client = sockClient.RemoteEndPoint.ToString();DicSocket.Add(client, sockClient);Invoke(myAddOnline, client, true);Invoke(myRcvMsg, client + "上线了!");//开启接受线程Thread thr = new Thread(ReceiveMsg);thr.IsBackground = true;thr.Start(sockClient);}}#endregion#region 接收线程/// <summary>/// 接收线程/// </summary>/// <param name="sockClient"></param>private void ReceiveMsg(object sockClient){Socket sckclient = sockClient as Socket;while (true){//定义一个2M缓冲区byte[] arrMsgRec = new byte[1024 * 1024 * 2];int length = -1;try{length = sckclient.Receive(arrMsgRec);}catch (Exception){string str = sckclient.RemoteEndPoint.ToString();Invoke(myRcvMsg, str + "下线了!");//从列表中移除URLInvoke(myAddOnline, str, false);DicSocket.Remove(str);break;}if (length == 0){string str = sckclient.RemoteEndPoint.ToString();Invoke(myRcvMsg, str + "下线了!");//从列表中移除URLInvoke(myAddOnline, str, false);DicSocket.Remove(str);break;}else{if (arrMsgRec[0] == 0){string strMsg = Encoding.UTF8.GetString(arrMsgRec, 1, length-1);string Msg = "[接收] " + sckclient.RemoteEndPoint.ToString() + " " + strMsg;Invoke(myRcvMsg, Msg);}if (arrMsgRec[0] == 1){Invoke(myFileSave, arrMsgRec,length);}}}}#endregion#region 委托方法体private void AddOnline(string url, bool bl){if (bl){this.lbOnline.Items.Add(url);}else{this.lbOnline.Items.Remove(url);}}private void RecMsg(string str){this.txt_Rcv.AppendText(str + Environment.NewLine);}private void FileSave(byte[] bt, int length){try{SaveFileDialog sfd = new SaveFileDialog();sfd.Filter = "word files(*.docx)|*.docx|txt files(*.txt)|*.txt|xls files(*.xls)|*.xls|All files(*.*)|*.*";if (sfd.ShowDialog() == DialogResult.OK){string fileSavePath = sfd.FileName;using (FileStream fs = new FileStream(fileSavePath, FileMode.Create)){fs.Write(bt, 1, length - 1);Invoke(new Action(() => this.txt_Rcv.AppendText("[保存] 保存文件成功" + fileSavePath + Environment.NewLine)));}}}catch (Exception ex){MessageBox.Show("保存异常" + ex.Message, "保存文件出现异常");}}#endregion#region 发送消息/// <summary>/// 发送消息/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_SendToSingle_Click(object sender, EventArgs e){string StrMsg = this.txt_Send.Text.Trim();byte[] arrMsg = Encoding.UTF8.GetBytes(StrMsg);byte[] arrSend = new byte[arrMsg.Length + 1];arrSend[0] = 0;Buffer.BlockCopy(arrMsg, 0, arrSend, 1, arrMsg.Length);if (this.lbOnline.SelectedItems.Count == 0){MessageBox.Show("请选择你要发送的对象!", "发送提示");return;}else{foreach (string item in this.lbOnline.SelectedItems){DicSocket[item].Send(arrSend);string Msg = "[发送] " + item + " " + StrMsg;Invoke(myRcvMsg, Msg);}}}#endregion#region 群发消息/// <summary>/// 群发消息/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_SendToAll_Click(object sender, EventArgs e){string StrMsg = this.txt_Send.Text.Trim();byte[] arrMsg = Encoding.UTF8.GetBytes(StrMsg);byte[] arrSend = new byte[arrMsg.Length + 1];arrSend[0] = 0;Buffer.BlockCopy(arrMsg, 0, arrSend, 1, arrMsg.Length);foreach (string item in this.DicSocket.Keys){DicSocket[item].Send(arrSend);string Msg = "[发送] " + item + " " + StrMsg;Invoke(myRcvMsg, Msg);}Invoke(myRcvMsg, "[群发] 群发完毕!");}#endregion#region 打开客户端/// <summary>/// 打开客户端/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_Client_Click(object sender, EventArgs e){FrmTCPClient objFrm = new FrmTCPClient();objFrm.Show();}#endregion#region 选择文件/// <summary>/// 选择文件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_SelectFile_Click(object sender, EventArgs e){OpenFileDialog ofd = new OpenFileDialog();ofd.InitialDirectory = "D:\\";if (ofd.ShowDialog() == DialogResult.OK){this.txt_SelectFile.Text = ofd.FileName;}}#endregion#region 发送文件/// <summary>/// 发送文件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_SendFile_Click(object sender, EventArgs e){if (string.IsNullOrEmpty(txt_SelectFile.Text)){MessageBox.Show("请选择您要发送的文件!", "发送文件提示");return;}string online = this.lbOnline.Text.Trim();if (string.IsNullOrEmpty(online)){MessageBox.Show("请选择您要发送的对象!", "发送文件提示");return;}using (FileStream fs = new FileStream(txt_SelectFile.Text, FileMode.Open)){string filename = Path.GetFileName(txt_SelectFile.Text);string StrMsg = "发送文件为:" + filename;byte[] arrMsg = Encoding.UTF8.GetBytes(StrMsg);byte[] arrSend= new byte[arrMsg.Length + 1];arrSend[0] =0;Buffer.BlockCopy(arrMsg, 0, arrSend, 1, arrMsg.Length);DicSocket[online].Send(arrSend);byte[] arrfileSend = new byte[1024 * 1024 * 2];int length = fs.Read(arrfileSend, 0, arrfileSend.Length);byte[] arrfile = new byte[length + 1];arrfile[0] = 1;Buffer.BlockCopy(arrfileSend, 0, arrfile, 1, length);DicSocket[online].Send(arrfile);}}#endregion}
}
2、客户端FrmClient.cs文件
FrmClient.cs窗体
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 SocketTCP
{delegate void FileSaveDelegate(byte[] bt,int length);public partial class FrmTCPClient : Form{public FrmTCPClient(){InitializeComponent();MyFileSave = FileSave;}//Socket对象Socket sockClient = null;//接收线程Thread thrClient = null;//运行标志位private bool IsRunning = true;//文件保存委托对象FileSaveDelegate MyFileSave;#region 连接服务器/// <summary>/// 连接服务器/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_Connect_Click(object sender, EventArgs e){IPAddress address = IPAddress.Parse(this.txt_IP.Text.Trim());IPEndPoint Ipe = new IPEndPoint(address, int.Parse(this.txt_Port.Text.Trim()));sockClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);try{this.txt_Rcv.AppendText("与服务器连接中......" + Environment.NewLine);sockClient.Connect(Ipe);}catch (Exception ex){MessageBox.Show("连接失败" + ex.Message, "建立连接");return;}this.txt_Rcv.AppendText("与服务器连接成功" + Environment.NewLine);this.btn_Connect.Enabled = false;thrClient = new Thread(ReceiceMsg);thrClient.IsBackground = true;thrClient.Start();}#endregion#region 接收消息/// <summary>/// 接收消息/// </summary>private void ReceiceMsg(){while (IsRunning){//定义一个2M缓冲区byte[] arrMsgRec = new byte[1024 * 1024 * 2];int length = -1;try{length = sockClient.Receive(arrMsgRec);}catch (SocketException){break;}catch (Exception ex){Invoke(new Action(() => this.txt_Rcv.AppendText("断开连接" + ex.Message + Environment.NewLine)));break;}if (length > 0){//表示接受到的为消息类型if (arrMsgRec[0] == 0){string strMsg = Encoding.UTF8.GetString(arrMsgRec, 1, length-1);string Msg = "[接收] " + strMsg + Environment.NewLine;Invoke(new Action(() => this.txt_Rcv.AppendText(Msg)));}//表示接收到的为文件类型if (arrMsgRec[0] == 1){Invoke(MyFileSave, arrMsgRec,length);}}}}#endregion#region 委托方法体private void FileSave(byte[] bt, int length){try{SaveFileDialog sfd = new SaveFileDialog();sfd.Filter = "word files(*.docx)|*.docx|txt files(*.txt)|*.txt|xls files(*.xls)|*.xls|All files(*.*)|*.*";if (sfd.ShowDialog() == DialogResult.OK){string fileSavePath = sfd.FileName;using (FileStream fs = new FileStream(fileSavePath, FileMode.Create)){fs.Write(bt, 1, length - 1);Invoke(new Action(() => this.txt_Rcv.AppendText("[保存] 保存文件成功" + fileSavePath+Environment.NewLine)));}}}catch (Exception ex){MessageBox.Show("保存异常" + ex.Message, "保存文件出现异常");}}#endregion#region 发送消息/// <summary>/// 发送消息/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_Send_Click(object sender, EventArgs e){string strMsg = "来自" + this.txt_Name.Text.Trim() + ": " + this.txt_Send.Text.Trim();byte[] arrMsg = Encoding.UTF8.GetBytes(strMsg);byte[] arrSend = new byte[arrMsg.Length + 1];arrSend[0] = 0;Buffer.BlockCopy(arrMsg, 0, arrSend, 1, arrMsg.Length);sockClient.Send(arrSend);Invoke(new Action(() => this.txt_Rcv.AppendText("[发送] " + this.txt_Send.Text.Trim() + Environment.NewLine)));}#endregion#region 窗体关闭事件/// <summary>/// 窗体关闭事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void FrmTCPClient_FormClosing(object sender, FormClosingEventArgs e){IsRunning = false;sockClient?.Close();}#endregion#region 选择文件/// <summary>/// 选择文件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_SelectFile_Click(object sender, EventArgs e){OpenFileDialog ofd = new OpenFileDialog();ofd.InitialDirectory = "D:\\";if (ofd.ShowDialog() == DialogResult.OK){this.txt_SelectFile.Text = ofd.FileName;}}#endregion#region 发送文件/// <summary>/// 发送文件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btn_SendFile_Click(object sender, EventArgs e){if (string.IsNullOrEmpty(txt_SelectFile.Text)){MessageBox.Show("请选择您要发送的文件!", "发送文件提示");return;}using (FileStream fs = new FileStream(txt_SelectFile.Text, FileMode.Open)){string filename = Path.GetFileName(txt_SelectFile.Text);string StrMsg = "发送文件为:" + filename;byte[] arrMsg = Encoding.UTF8.GetBytes(StrMsg);byte[] arrSend = new byte[arrMsg.Length + 1];arrSend[0] = 0;Buffer.BlockCopy(arrMsg, 0, arrSend, 1, arrMsg.Length);sockClient.Send(arrSend);byte[] arrfileSend = new byte[1024 * 1024 * 2];int length = fs.Read(arrfileSend, 0, arrfileSend.Length);byte[] arrfile = new byte[length + 1];arrfile[0] = 1;Buffer.BlockCopy(arrfileSend, 0, arrfile, 1, length);sockClient.Send(arrfile);}}#endregion}
}
3、启动文件Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;namespace SocketTCP
{static class Program{/// <summary>/// 应用程序的主入口点。/// </summary>[STAThread]static void Main(){Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault(false);Application.Run(new FrmTCPServer());}}
}