最近接触了C#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 kehuduan { public partial class Form1 : Form { public Form1() { InitializeComponent(); } Dictionary<string,Socket> dicsocket = new Dictionary<string, Socket>();//键值集合,通过键能找到值 private void button1_Click(object sender, EventArgs e) { try { //创建监听的socket Socket socketwatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //获得ip地址 IPAddress ip = IPAddress.Any;//Parse(textBox1.Text); //创建端口号对象 IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(textBox2.Text)); socketwatch.Bind(point); showmsg(DateTime.Now.ToString() + "监听成功");//192.168.1.103:监听成功 socketwatch.Listen(10);//开始监听。监听队列10人 //开启新线程解决卡顿 Thread lis = new Thread(Listen); lis.IsBackground = true; lis.Start(socketwatch); } catch { } } Socket socketsend; /// <summary> /// 循环等待接入的客户端 /// </summary> /// <param name="o"></param> void Listen(object o) { try { Socket socketwatch = o as Socket; while (true) { //负责跟客户端通信的Socket socketsend = socketwatch.Accept(); //把连进来的socket存到建值集合和下拉菜单中,实现给指定的客户端发消息 dicsocket.Add(socketsend.RemoteEndPoint.ToString(),socketsend); comboBox1.Items.Add(socketsend.RemoteEndPoint.ToString());//socket.remoteendpoint可以显示socket的ip地址和端口号 //192.168.1.103:连接成功 showmsg(socketsend.RemoteEndPoint.ToString() + ":" + "连接成功"); //连接成功后开启新线程接受消息 Thread th = new Thread(Recive); th.IsBackground = true; th.Start(socketsend); } } catch { } } /// <summary> /// 服务器端循环接收客户端发来的信息 /// </summary> /// <param name="o"></param> void Recive(object o) { while (true) { try { Socket socketsend = o as Socket; byte[] b = new byte[1024 * 1024 * 2]; //实际接收到的有效字节 int r = socketsend.Receive(b); if (r == 0) { break; } string str = Encoding.UTF8.GetString(b, 0, r); showmsg(socketsend.RemoteEndPoint.ToString() + "说:" + str); } catch { } } } /// <summary> /// 往文本框里添加文字的方法 /// </summary> /// <param name="a"></param> void showmsg(string a) { textBox3.AppendText(a+"\r\n"); } private void textBox1_TextChanged(object sender, EventArgs e) { } private void Form1_Load(object sender, EventArgs e) { Control.CheckForIllegalCrossThreadCalls = false; } /// <summary> /// 服务器给客户端发文字消息 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button4_Click(object sender, EventArgs e) { try { List<byte> nb = new List<byte>(); string str = textBox4.Text.Trim(); byte[] b = System.Text.Encoding.UTF8.GetBytes(str); nb.Add(0); nb.AddRange(b); byte[] newb = nb.ToArray(); string ip = comboBox1.SelectedItem.ToString(); dicsocket[ip].Send(newb); //socketsend.Send(b); showmsg("我说 :" + str); } catch { } } /// <summary> /// 选择要发送的文件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button2_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.InitialDirectory = @"C:\Documents and Settings\Administrator\桌面"; ofd.Title = "请选择要发送的文件"; ofd.Filter = "所有文件|*.*"; ofd.ShowDialog(this);//加this textBox5.Text = ofd.FileName; } /// <summary> /// 向客户端发送文件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button3_Click(object sender, EventArgs e) { try { string path = textBox5.Text; using (FileStream fsread = new FileStream(path, FileMode.Open, FileAccess.Read)) //把文件转换为文件流 { byte[] b = new byte[1024 * 1024 * 5];//最大5m的文件 int r = fsread.Read(b, 0, b.Length); List<byte> nb = new List<byte>(); nb.Add(1);//在第一位加上数字,让客户端可以识别服务端的指令 nb.AddRange(b);//往集合中添加集合的方法。 byte[] newb = nb.ToArray(); dicsocket[comboBox1.SelectedItem.ToString()].Send(newb, 0, r + 1, SocketFlags.None); } } catch { } } /// <summary> /// 抖动窗口 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button5_Click(object sender, EventArgs e)//发送消息 { try { byte[] b = new byte[1]; b[0] = 2; dicsocket[comboBox1.SelectedItem.ToString()].Send(b); } catch { } } } }
客户端:
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 kehuduan { public partial class Form1 : Form { public Form1() { InitializeComponent(); } Socket socketsend; private void button1_Click(object sender, EventArgs e) { try { socketsend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//设置一个socket IPAddress ip = IPAddress.Parse(textBox1.Text);//将文本框中的字符串转换成IP地址。 IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(textBox2.Text));//创建IPEndpoint对象实例。包含ip地址和端口号 socketsend.Connect(point);//连接到IPendpoint所在的监听socket showmsg("连接成功"); //开启新线程 Thread th = new Thread(Recive); th.IsBackground = true; th.Start(); } catch { } } void showmsg(string str) //在文本框中添加内容 { textBox3.AppendText(str+"\r\n"); } private void Form1_Load(object sender, EventArgs e) { Control.CheckForIllegalCrossThreadCalls = false;//取消跨线程使用控件检查。 } void Recive()//接收 { while (true) { try { byte[] b = new byte[1024 * 1024 * 2]; //实际接收到的有效字节 int r = socketsend.Receive(b); if (r == 0) { break; } if (b[0] == 0) { string str = Encoding.UTF8.GetString(b, 1, r-1); //从第二个开始截取,因为第一个元素用来判断服务端发过来的指令。 showmsg(socketsend.RemoteEndPoint.ToString() + "说:" + str); } else if (b[0] == 1) { SaveFileDialog sfd = new SaveFileDialog();//保存文件对话框 sfd.InitialDirectory = @"C:\Documents and Settings\Administrator\桌面"; sfd.Title = "对方发送了一个文件,请选择保存的位置"; sfd.ShowDialog(); string path = sfd.FileName; using (FileStream fswrite = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))//数据流控制,用来保存文件。 { fswrite.Write(b,1,r-1); MessageBox.Show("保存成功"); } } else if (b[0] == 2)//如果发来的字节包首个元素的值==2,就振动 { ZD(); } } catch { } } } private void button2_Click(object sender, EventArgs e)//发送消息 { try { string str = textBox4.Text.Trim();//存下文本框中的内容 byte[] b = System.Text.Encoding.UTF8.GetBytes(str);//将内容转换成二进制流(utf8编码) socketsend.Send(b);//发送给服务端 showmsg("我说 :" + str);//将我说的话放到文本框中 } catch { } } /// <summary> /// 震动窗体 /// </summary> void ZD()//连续修改窗口的Location,模拟抖动窗口效果 { for (int i = 0; i < 50; i++) { Point a = this.Location; a.X += 5; a.Y += 5; this.Location = a; Thread.Sleep(2); a.X -=5; a.Y -=5; this.Location = a; } } } }
知识点
//跨线程使用控件应在窗口加载时取消检查。
//跨线程方法传值只能传Object类型的值,可以在方法中强制转换成需要的类型,如 socketwatch = Object AS socket(将AS前的对象转换成后边的对象,如果成功返回转换成功后的对象,否则返回null)
//键值集合
Dictionary<键,值> 集合名 = new Dictionary<键, 值>();
集合名.add(键,值)//往集合里添加
使用 集合名[键] 可以访问键对应的值。