C#里面封装好了Socket,直接引用即可使用
关键字:using System.Net;
using.System.Sockets;
创建一个负责监听的Socket:Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
第一个参数是IPV42,第二个为流式,TCP用流式,UDP用数式,第三个为协议类型
IP地址获取:IPAddress ip = IPAddress.Any;
Any是指当前服务器的所有ip
端口获取:IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
这里获取的文本框里的端口。
将负责监听的Socket绑定IP地址和端口:socketWatch.Bind(point);
设置监听队列,某一时间段最大连接数:socketWatch.Listen(100);
这样一个Socket就创建好了。
下面是接受连接:
//负责监听的Socket来接收客户端的连接 while (true) { //负责跟客户端通信的Socket socketSend = socketWatch.Accept(); //将远程连接的客户端的IP和Socket存入集合中 dicSocket.Add(socketSend.RemoteEndPoint.ToString(), socketSend); //将远程连接的客户端的IP地址和端口号存储到下拉框中 this.Invoke(new Action(addCbomDic)); //连接成功 this.Invoke(new Action<string>(ShowMsg), socketSend.RemoteEndPoint.ToString() + "连接成功"); // ShowMsg(socketSend.RemoteEndPoint.ToString() + "连接成功"); //接收客户端消息线程 Task.Run(() => Recive(socketSend)); }
以上就是Socket部分的主要代码了,下面是服务端的主要实现代码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; namespace MonitorTest { public partial class Form1 : Form { Socket socketSend; //将远程客户端的IP地址和Socket存入集合中 Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>(); public Form1() { InitializeComponent(); } private void btnsStart_Click(object sender, EventArgs e) { //创建一个负责监听得Socket //第一个参数是IPV42,第二个为流式,TCP用流式,UDP用数式,第三个为协议类型 Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //创建IP地址和端口号对象 IPAddress ip = IPAddress.Any; //IPAddress.Parse(txtServer.Text); IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text)); //让负责监听的Socket绑定IP地址跟端口号 socketWatch.Bind(point); ShowMsg("监听成功"); //设置监听队列,某一时间点能够连入客户端的最大数量+ socketWatch.Listen(100); Task.Run(()=>Listen(socketWatch)); } /// <summary> /// 等待客户端的连接,并且创建一个负责通信的Socket /// </summary> void Listen(Socket socketWatch) { //负责监听的Socket来接收客户端的连接 while (true) { //负责跟客户端通信的Socket socketSend = socketWatch.Accept(); //将远程连接的客户端的IP和Socket存入集合中 dicSocket.Add(socketSend.RemoteEndPoint.ToString(), socketSend); //将远程连接的客户端的IP地址和端口号存储到下拉框中 this.Invoke(new Action(addCbomDic)); //连接成功 this.Invoke(new Action<string>(ShowMsg), socketSend.RemoteEndPoint.ToString() + "连接成功"); // ShowMsg(socketSend.RemoteEndPoint.ToString() + "连接成功"); //接收客户端消息线程 Task.Run(() => Recive(socketSend)); } } /// <summary> /// 将数据添加到下拉列表中 /// </summary> void addCbomDic() { cboUsers.Items.Add(socketSend.RemoteEndPoint.ToString()); } /// <summary> /// 接受客户端发来的消息 /// </summary> /// <param name="socketSend"></param> void Recive(Socket socketSend) { while (true) { try { //客户端连接成功后,服务器应该接受客户端发来的消息 byte[] buffer = new byte[1024 * 1024 * 4]; //实际接收到的有效字节数 int r = socketSend.Receive(buffer); if (r == 0) { break; } string str = Encoding.UTF8.GetString(buffer, 0, r); this.Invoke(new Action<string>(ShowMsg), socketSend.RemoteEndPoint.ToString() + " : " + str); } catch { } } } void ShowMsg(string str) { txtLog.AppendText(str + "\r\n"); } 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 = txtMsg.Text; byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str); List<byte> list = new List<byte>(); list.Add(0); list.AddRange(buffer); byte[] newBuffer = list.ToArray(); try { //获得用户在下拉框中选中的IP地址 string ip = cboUsers.SelectedItem.ToString(); dicSocket[ip].Send(newBuffer); ShowMsg(str); } catch { } // socketSend.Send(newBuffer); } /// <summary> /// 选择要发送的文件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSelect_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.InitialDirectory = @"D:\Document\Test"; ofd.Title = "请选择要发送的文件"; ofd.Filter = "所有文件|*.*"; ofd.ShowDialog(); txtPath.Text = ofd.FileName; } private void btnSendFile_Click(object sender, EventArgs e) { //获得要发送文件的路径 string path = txtPath.Text; using (FileStream fsRead = new FileStream(path, FileMode.Open, FileAccess.Read)) { byte[] buffer = new byte[1024 * 1024 * 8]; int r = fsRead.Read(buffer,0,buffer.Length); List<byte> list = new List<byte>(); list.Add(1); list.AddRange(buffer); byte[] newBuffer = list.ToArray(); dicSocket[cboUsers.SelectedItem.ToString()].Send(newBuffer, 0, r+1, SocketFlags.None); } } /// <summary> /// 发送震动 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnShake_Click(object sender, EventArgs e) { byte[] buffer = new byte[1]; buffer[0] = 2; dicSocket[cboUsers.SelectedItem.ToString()].Send(buffer); } } }
客户端主要代码:
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.Tasks; using System.Windows.Forms; namespace ClientSimple { public partial class Form1 : Form { Socket socketSend; public Form1() { InitializeComponent(); } private void btnsStart_Click(object sender, EventArgs e) { try { //创建负责通信的Socket socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress ip = IPAddress.Parse(txtServer.Text.Trim()); IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text.Trim())); //获得要链接的远程服务器应用程序的IP地址和端口号 socketSend.Connect(point); ShowMsg("连接成功"); Task.Run(() => Recive()); } catch { } } /// <summary> /// 不停的接受服务器发来的消息 /// </summary> void Recive() { while (true) { try { //客户端连接成功后,服务器应该接受客户端发来的消息 byte[] buffer = new byte[1024 * 1024 * 4]; int r = socketSend.Receive(buffer); //实际接收到的有效字节数 if (r == 0) { break; } if (buffer[0] == 0) { string str = Encoding.UTF8.GetString(buffer, 1, r-1); this.Invoke(new Action<string>(ShowMsg), socketSend.RemoteEndPoint.ToString() + " : " + str); } else if (buffer[0] == 1) { this.Invoke(new Action<byte[], int>(SaveFile), buffer, r); } else if (buffer[0] == 2) { this.Invoke(new Action(Shake)); } } catch { } } } /// <summary> /// 震动 /// </summary> void Shake() { for (int i = 0; i < 500; i++) { this.Location = new Point(200, 200); this.Location = new Point(280, 280); } } /// <summary> /// 存储文件 /// </summary> void SaveFile(byte[] buffer,int r) { SaveFileDialog sfd = new SaveFileDialog(); sfd.InitialDirectory = @"D:\Document\Test"; sfd.Title = "请选择要保存到路径"; sfd.Filter = "所有文件|*.*"; sfd.ShowDialog(this); string path = sfd.FileName; using (FileStream fsWrite = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write)) { fsWrite.Write(buffer, 1, r - 1); } MessageBox.Show("保存成功"); } void ShowMsg(string str) { txtLog.AppendText(str + "\r\n"); } /// <summary> /// 客户端给服务器发送消息 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSend_Click(object sender, EventArgs e) { string str = txtMsg.Text.Trim(); byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str); ShowMsg(str); socketSend.Send(buffer); } private void Form1_Load(object sender, EventArgs e) { //Control.CheckForIllegalCrossThreadCalls = false; } } }
实现效果图:
总结:创建Socket过程,发送数据socket.Send()方法。接收数据socket.Receive()。
这个demo还非常简陋,有很多地方没有完善。主要目的Socket学习,所以很多能看见的Bug就没处理。客户端连接成功后,服务端要选择下拉列表中的客户端才能发信息,不然直接发就报错了。文件发送也不能为空,接收文件也不能取消,接收文件也不知道文件的后缀(类型)。。。。。。