直接上代码,注释俺写了不少,留着参考
服务端:
1 namespace sever 2 { 3 public partial class Form1 : Form 4 { 5 public Form1() 6 { 7 InitializeComponent(); 8 } 9 10 private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) 11 { 12 13 } 14 15 16 private void btnStart_Click(object sender, EventArgs e) 17 { 18 try//但凡网络上的程序,总会出现各种各样的异常,用户断电,断网等等等等.....所以要踹一脚 19 { 20 //当点击开始监听时,在服务器端创建一个负责监听IP地址和端口号的Socket 21 Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 22 IPAddress ip = IPAddress.Any; 23 //创建端口号对象 24 IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text)); 25 //监听 26 socketWatch.Bind(point); 27 ShowMsg("监听成功"); 28 socketWatch.Listen(10); 29 30 Thread th = new Thread(Listen); 31 th.IsBackground = true; 32 th.Start(socketWatch); 33 } 34 catch//catch里什么都不写,哪怕用户出异常了也不会显示任何内容,在用户看来,程序没有异常 35 { } 36 37 } 38 Socket socketSend; 39 /// <summary> 40 /// 循环等待客户端的连接 并且创建与之通信用的Socket 41 /// </summary> 42 void Listen(object o) 43 { 44 try 45 { 46 Socket socketWatch = o as Socket; 47 //等待客户端的连接 并且创建一个负责通信的Socket 48 while (true) 49 { 50 socketSend = socketWatch.Accept(); 51 //将远程连接的客户端的IP地址和Socket存到键值对集合中 52 dicSocket.Add(socketSend.RemoteEndPoint.ToString(), socketSend); 53 //将远程连接的客户端的IP地址和端口号存到下拉框当中 54 cboUsers.Items.Add(socketSend.RemoteEndPoint.ToString()); 55 ShowMsg(socketSend.RemoteEndPoint.ToString() + ":" + "连接成功"); 56 //再开启一个新线程不停的接收客户端发送来的消息 57 Thread th = new Thread(Recive); 58 th.IsBackground = true; 59 th.Start(socketSend); 60 } 61 } 62 catch 63 { } 64 } 65 66 //将远程连接的客户端的IP地址和Socket存到键值对集合中 67 Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>(); 68 69 /// <summary> 70 /// 接收数据,服务器端不停的接收客户端发送来的消息 71 /// </summary> 72 void Recive(object o) 73 { 74 Socket socketSend = o as Socket; 75 while (true) 76 { 77 try 78 { 79 //客户端连接成功后,服务器接收客户端发来的消息 80 byte[] buffer = new byte[1024 * 1024 * 2]; 81 //实际接收到的有效字节数 82 int r = socketSend.Receive(buffer); 83 if (r == 0) 84 { 85 break; 86 } 87 string str = Encoding.UTF8.GetString(buffer, 0, r); 88 ShowMsg(socketSend.RemoteEndPoint + ":" + str); 89 } 90 catch 91 { } 92 } 93 } 94 /// <summary> 95 /// 追加文本,日志列表,用追加可以观察客户端发来的消息 96 /// </summary> 97 /// <param name="str"></param> 98 void ShowMsg(string str) 99 { 100 txtLog.AppendText(str + "\r\n"); 101 } 102 103 private void Form1_Load(object sender, EventArgs e) 104 { 105 Control.CheckForIllegalCrossThreadCalls = false; 106 } 107 /// <summary> 108 /// 服务器给客户端发送消息 109 /// </summary> 110 /// <param name="sender"></param> 111 /// <param name="e"></param> 112 private void btnSend_Click(object sender, EventArgs e) 113 { 114 try 115 { 116 string str = txtMsg.Text.Trim(); 117 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(str); 118 // 119 List<byte> list = new List<byte>(); 120 list.Add(0); 121 list.AddRange(buffer); 122 //将泛型集合转换为数组 123 byte[] newBuffer = list.ToArray(); 124 //获得用户在下拉框中选中的IP地址 125 string ip = cboUsers.SelectedItem.ToString(); 126 dicSocket[ip].Send(newBuffer); 127 // socketSend.Send(buffer); 128 } 129 catch { } 130 } 131 /// <summary> 132 /// 选择要发送的文件 133 /// </summary> 134 /// <param name="sender"></param> 135 /// <param name="e"></param> 136 private void btnSelect_Click(object sender, EventArgs e) 137 { 138 try 139 { 140 OpenFileDialog ofd = new OpenFileDialog(); 141 //设置初始目录 142 ofd.InitialDirectory = @"C:\Users\Administrator\Desktop"; 143 ofd.Title = "请选择要发送的文件"; 144 ofd.Filter = "所有文件|*.*"; 145 ofd.ShowDialog(); 146 147 txtPath.Text = ofd.FileName; 148 } 149 catch { } 150 } 151 /// <summary> 152 /// 发送文件 153 /// </summary> 154 /// <param name="sender"></param> 155 /// <param name="e"></param> 156 private void btnSendFile_Click(object sender, EventArgs e) 157 { 158 try 159 { 160 //获得要发送文件的路径 161 string path = txtPath.Text; 162 using (FileStream fsRead = new FileStream(path, FileMode.Open, FileAccess.Read)) 163 { 164 byte[] buffer = new byte[1024 * 1024 * 5]; 165 int r = fsRead.Read(buffer, 0, buffer.Length); 166 167 List<byte> list = new List<byte>(); 168 list.Add(1); 169 list.AddRange(buffer); 170 byte[] newBuffer = list.ToArray(); 171 //由于第一个元素是用来判断接收的是什么类型数据,所以服务器端必须发送给客户端,以便客户端进行判断 172 //故:转换字符串时,从第1个元素开始,有效字节数+1 173 dicSocket[cboUsers.SelectedItem.ToString()].Send(newBuffer, 0, r + 1, SocketFlags.None); 174 } 175 } 176 catch { } 177 } 178 /// <summary> 179 /// 发送震动 180 /// </summary> 181 /// <param name="sender"></param> 182 /// <param name="e"></param> 183 private void btnZD_Click(object sender, EventArgs e) 184 { 185 byte[] buffer = new byte[1]; 186 buffer[0] = 2; 187 dicSocket[cboUsers.SelectedItem.ToString()].Send(buffer); 188 } 189 } 190 }
客户端:
namespace _02Client { public partial class Form1 : Form { public Form1() { InitializeComponent(); } Socket socketSend; private void btnStart_Click(object sender, EventArgs e) { try { //创建负责通信的Socket socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress ip = IPAddress.Parse(txtSever.Text); IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPorit.Text)); socketSend.Connect(point); ShowMsg("连接成功"); //开启一个新线程接收服务端发来的消息 Thread th = new Thread(Recive); th.IsBackground = true; th.Start(); } catch { ShowMsg("服务器连接失败"); } } 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); socketSend.Send(buffer); } /// <summary> /// 不听的接收服务端发来的消息 /// </summary> void Recive() { //socketSend = o as Socket; //不停的接收服务端发来的消息 while (true) { try { byte[] buffer = new byte[1024 * 1024 * 2]; //实际接收到的有效字节数 int r = socketSend.Receive(buffer); if (r == 0) { break; } //我们把服务器发送的类型做一个标记 //0:表示发送的是文本;1:表示发送的是文件;2:表示发送的是震动 int n = buffer[0]; //表示发送的是文字消息 if (n == 0)//接收文字消息 { //由于第一个元素是用来判断接收的是什么类型数据,所以不能解码返回显示给用户, //故:转换字符串时,从第二个元素开始,有效字节数-1 string str = Encoding.UTF8.GetString(buffer, 1, r - 1); //string str = Encoding.UTF8.GetString(buffer, 0, r); ShowMsg(socketSend.RemoteEndPoint + ":" + str); } else if (n == 1)//接收文件 { SaveFileDialog sfd = new SaveFileDialog(); //初始保存路径 sfd.InitialDirectory = @"C:\Users\Administrator\Desktop"; sfd.Title = "请选择要保存的文件"; 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); } MessageBox.Show("保存成功"); } else if (n == 2)//接收震动 { ZD(); } } catch { //ShowMsg("网络断开"); } } } /// <summary> /// 震动 /// </summary> void ZD() { for (int i = 0; i < 500; i++) { this.Location = new Point(200, 200); this.Location = new Point(205, 205); } } private void Form1_Load(object sender, EventArgs e) { Control.CheckForIllegalCrossThreadCalls = false; } } }