步骤:
一、服务端的建立
1.服务端的项目建立以及页面布局
2.各功能按键的事件代码
1)传输类型说明以及全局变量
2)Socket通信服务端具体步骤:
(1)建立一个Socket
(2)接收信息
(3)发送数据(这里分发送字符串、文件(包含大文件)、震动)
二、客户端的建立
1.服务端的项目建立以及页面布局
2.各功能按键的事件代码
1)传输类型说明以及全局变量
2)Socket通信服务端具体步骤:
(1)建立一个Socket
(2)接收信息
(3)发送数据(这里分发送字符串、文件(包含大文件)、震动)
注意:此图是Socket通信的精华,在使用Socket通信时,有什么迷惑的可以看看此图,下面我们讲解的时候也是参照此图
Socket大家肯定很熟悉,对已内部的通信逻辑,肯定也有一定得了解—
对于Socket研究了两天写了一个小程序,通过Socket服务端与客户端的通信,以及大文件之间断点的传输(这里只做了服务端给客户端传送大文件,如果想把客户端的大文件传送给服务端也是一样的道理,看了文章,大家肯定可以自己实现)······
(自己才疏学浅,如有bug请谅解,但功能还是能实现的)
下面根据步骤进入正题:
一、服务端的建立
1.服务端的项目建立以及页面布局
新建解决方案“Socket通信”以及两个Winform项目(1)SockeClient——客户端 (2)SocketServer——服务器
给服务端界面布局——参照上图(这个大家肯定都是手到擒来就不累赘了······)
2.各功能按键的事件代码
先把整个服务端的代码贴出来,然后我们在一一讲解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
|
1)传输类型说明以及全局变量
这些说明以及全局变量,说的也比较清楚,也不累赘了。
2)Socket通信服务端具体步骤:
(这些步骤都是根据第一个图来的)
(1)建立一个Socket
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
在开启监听按钮里,我们建立了Socket,以及监听的最大客户端数 socketWatch.Listen(10)
由于服务端会不停的去监视接收客户端发来的信息,如果把这个工作放到主线程里,程序会出现假死的现象,所以这里给他放到一个新的线程里。
(2)接收信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
接收信息是会根据接收到字节数字的第一个字节来判断接收到的是什么
这个在方法Recive里进行判断
1 |
|
namespace SocketClient { public partial class Form1 : Form { //说明:在传递信息的时候,会在需要传递的信息前面加一个字符来标识传递的是不同的信息 // 0:表示传递的是字符串信息 // 1:表示传递的是文件信息 // 2:表示的是震动 /// <summary> /// 用来存放连接服务的IP地址和端口号,对应的Socket (这个为了以后的扩展用,现在暂时没用) /// </summary> Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>(); /// <summary> /// 存储保存文件的路径 /// </summary> string filePath = ""; /// <summary> /// 负责通信的Socket /// </summary> Socket socketSend; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { //不检测跨线程之间的空间调用 Control.CheckForIllegalCrossThreadCalls = false; } /// <summary> /// 建立连接 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnStart_Click(object sender, EventArgs e) { try { //创建负责通信的Socket socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //获取服务端的IP IPAddress ip = IPAddress.Parse(txtServer.Text.Trim()); //获取服务端的端口号 IPEndPoint port = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text)); //获得要连接的远程服务器应用程序的IP地址和端口号 socketSend.Connect(port); ShowMsg("连接成功"); //新建线程,去接收客户端发来的信息 Thread td = new Thread(AcceptMgs); td.IsBackground = true; td.Start(); } catch { } } /// <summary> /// 接收数据 /// </summary> private void AcceptMgs() { try { /// <summary> /// 存储大文件的大小 /// </summary> long length = 0; long recive = 0; //接收的大文件总的字节数 while (true) { byte[] buffer = new byte[1024 * 1024]; int r = socketSend.Receive(buffer); if (r == 0) { break; } if (length > 0) //判断大文件是否已经保存完 { //保存接收的文件 using (FileStream fsWrite = new FileStream(filePath, FileMode.Append, FileAccess.Write)) { fsWrite.Write(buffer, 0, r); length -= r; //减去每次保存的字节数 ShowMsg(string.Format("{0}: 已接收:{1}/{2}", socketSend.RemoteEndPoint, recive-length, recive)); if (length <= 0) { ShowMsg(socketSend.RemoteEndPoint + ": 接收文件成功"); } continue; } } if (buffer[0] == 0) //如果接收的字节数组的第一个字节是0,说明接收的字符串信息 { string strMsg = Encoding.UTF8.GetString(buffer, 1, r - 1); ShowMsg(socketSend.RemoteEndPoint.ToString() + ": " + strMsg); } else if (buffer[0] == 1) //如果接收的字节数组的第一个字节是1,说明接收的是文件 { length = int.Parse(Encoding.UTF8.GetString(buffer,1,r-1)); recive = length; filePath = ""; SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "保存文件"; sfd.InitialDirectory = @"C:\Users\Administrator\Desktop"; sfd.Filter = "文本文件|*.txt|图片文件|*.jpg|视频文件|*.avi|所有文件|*.*"; //如果没有选择保存文件路径就一直打开保存框 while (true) { sfd.ShowDialog(this); filePath = sfd.FileName; if (string.IsNullOrEmpty(filePath)) { continue; } else { break; } } } else if (buffer[0] == 2) //如果接收的字节数组的第一个字节是2,说明接收的是震动 { ZD(); } } } catch { } } /// <summary> /// 显示信息 /// </summary> /// <param name="message"></param> private void ShowMsg(string message) { txtLog.AppendText(message + "\r\n"); } /// <summary> /// 发送数据 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSend_Click(object sender, EventArgs e) { try { byte[] buffer = Encoding.UTF8.GetBytes(txtMsg.Text); //获得发送的信息时候,在数组前面加上一个字节 0 List<byte> list = new List<byte>(); list.Add(0); list.AddRange(buffer); //将泛型集合转换为数组 byte[] newBuffer = list.ToArray(); //将了标识字符的字节数组传递给客户端 socketSend.Send(newBuffer); txtMsg.Text = ""; } catch{} } /// <summary> /// 选择文件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSelect_Click(object sender, EventArgs e) { //打开文件 OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "选择要传的文件"; ofd.InitialDirectory = @"C:\Users\Administrator\Desktop"; ofd.Filter = "文本文件|*.txt|图片文件|*.jpg|视频文件|*.avi|所有文件|*.*"; ofd.ShowDialog(); //得到选择文件的路径 txtPath.Text = ofd.FileName; } /// <summary> /// 发送文件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSendFile_Click(object sender, EventArgs e) { try { string filePath = txtPath.Text; if (string.IsNullOrEmpty(filePath)) { MessageBox.Show("请选择文件"); return; } //读取选择的文件 using (FileStream fsRead = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Read)) { byte[] buffer = new byte[1024 * 1024 * 2]; int r = fsRead.Read(buffer, 0, buffer.Length); //获得发送的信息时候,在数组前面加上一个字节 1 List<byte> list = new List<byte>(); list.Add(1); list.AddRange(buffer); byte[] newBuffer = list.ToArray(); //将了标识字符的字节数组传递给客户端 socketSend.Send(newBuffer, 0, r + 1, SocketFlags.None); txtPath.Text = ""; } } catch{ } } /// <summary> /// 震动 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnZD_Click(object sender, EventArgs e) { try { // 首字节是2说明是震动 byte[] buffer = new byte[1]; buffer[0] = 2; socketSend.Send(buffer); } catch{ } } /// <summary> /// 震动 /// </summary> private void ZD() { //获取当前窗体的坐标 Point point = this.Location; //反复给窗体坐标复制一百次,达到震动的效果 for (int i = 0; i < 100; i++) { this.Location = new Point(point.X - 5, point.Y - 5); this.Location = new Point(point.X + 5, point.Y + 5); } this.Location = point; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
|
(3)发送数据(这里分发送字符串、文件(包含大文件)、震动)
发送字符串信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
发送震动
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
|
发送文件(包含大文件)
首先要选择文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
然后在发送文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
|
注意:(1)发送文件的时候会分两步发送 :第一步:发送一个包,表示文件的长度,让客户端知道后续要接收几个包来重新组织成一个文件
第二步:每次发送一个1MB的包,如果文件较大,则会拆分为多个包
(2)每个客户端连接服务端的啥时候,都会把客户端的ip以及端口号,放到下拉框里,想给那个客户端发信息,就选择对应的客户端
二、客户端的建立
1.客户端的项目建立以及页面布局
客户端的界面布局与服务端很像,就是把对应的开始监听换成连接,当然代码也会有所改变,后面会讲到·····
2.各功能按键的事件代码
先把整个服客户端的代码贴出来,然后我们在一一讲解
namespace SocketClient { public partial class Form1 : Form { //说明:在传递信息的时候,会在需要传递的信息前面加一个字符来标识传递的是不同的信息 // 0:表示传递的是字符串信息 // 1:表示传递的是文件信息 // 2:表示的是震动 /// <summary> /// 用来存放连接服务的IP地址和端口号,对应的Socket (这个为了以后的扩展用,现在暂时没用) /// </summary> Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>(); /// <summary> /// 存储保存文件的路径 /// </summary> string filePath = ""; /// <summary> /// 负责通信的Socket /// </summary> Socket socketSend; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { //不检测跨线程之间的空间调用 Control.CheckForIllegalCrossThreadCalls = false; } /// <summary> /// 建立连接 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnStart_Click(object sender, EventArgs e) { try { //创建负责通信的Socket socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //获取服务端的IP IPAddress ip = IPAddress.Parse(txtServer.Text.Trim()); //获取服务端的端口号 IPEndPoint port = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text)); //获得要连接的远程服务器应用程序的IP地址和端口号 socketSend.Connect(port); ShowMsg("连接成功"); //新建线程,去接收客户端发来的信息 Thread td = new Thread(AcceptMgs); td.IsBackground = true; td.Start(); } catch { } } /// <summary> /// 接收数据 /// </summary> private void AcceptMgs() { try { /// <summary> /// 存储大文件的大小 /// </summary> long length = 0; long recive = 0; //接收的大文件总的字节数 while (true) { byte[] buffer = new byte[1024 * 1024]; int r = socketSend.Receive(buffer); if (r == 0) { break; } if (length > 0) //判断大文件是否已经保存完 { //保存接收的文件 using (FileStream fsWrite = new FileStream(filePath, FileMode.Append, FileAccess.Write)) { fsWrite.Write(buffer, 0, r); length -= r; //减去每次保存的字节数 ShowMsg(string.Format("{0}: 已接收:{1}/{2}", socketSend.RemoteEndPoint, recive-length, recive)); if (length <= 0) { ShowMsg(socketSend.RemoteEndPoint + ": 接收文件成功"); } continue; } } if (buffer[0] == 0) //如果接收的字节数组的第一个字节是0,说明接收的字符串信息 { string strMsg = Encoding.UTF8.GetString(buffer, 1, r - 1); ShowMsg(socketSend.RemoteEndPoint.ToString() + ": " + strMsg); } else if (buffer[0] == 1) //如果接收的字节数组的第一个字节是1,说明接收的是文件 { length = int.Parse(Encoding.UTF8.GetString(buffer,1,r-1)); recive = length; filePath = ""; SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "保存文件"; sfd.InitialDirectory = @"C:\Users\Administrator\Desktop"; sfd.Filter = "文本文件|*.txt|图片文件|*.jpg|视频文件|*.avi|所有文件|*.*"; //如果没有选择保存文件路径就一直打开保存框 while (true) { sfd.ShowDialog(this); filePath = sfd.FileName; if (string.IsNullOrEmpty(filePath)) { continue; } else { break; } } } else if (buffer[0] == 2) //如果接收的字节数组的第一个字节是2,说明接收的是震动 { ZD(); } } } catch { } } /// <summary> /// 显示信息 /// </summary> /// <param name="message"></param> private void ShowMsg(string message) { txtLog.AppendText(message + "\r\n"); } /// <summary> /// 发送数据 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSend_Click(object sender, EventArgs e) { try { byte[] buffer = Encoding.UTF8.GetBytes(txtMsg.Text); //获得发送的信息时候,在数组前面加上一个字节 0 List<byte> list = new List<byte>(); list.Add(0); list.AddRange(buffer); //将泛型集合转换为数组 byte[] newBuffer = list.ToArray(); //将了标识字符的字节数组传递给客户端 socketSend.Send(newBuffer); txtMsg.Text = ""; } catch{} } /// <summary> /// 选择文件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSelect_Click(object sender, EventArgs e) { //打开文件 OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "选择要传的文件"; ofd.InitialDirectory = @"C:\Users\Administrator\Desktop"; ofd.Filter = "文本文件|*.txt|图片文件|*.jpg|视频文件|*.avi|所有文件|*.*"; ofd.ShowDialog(); //得到选择文件的路径 txtPath.Text = ofd.FileName; } /// <summary> /// 发送文件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSendFile_Click(object sender, EventArgs e) { try { string filePath = txtPath.Text; if (string.IsNullOrEmpty(filePath)) { MessageBox.Show("请选择文件"); return; } //读取选择的文件 using (FileStream fsRead = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Read)) { byte[] buffer = new byte[1024 * 1024 * 2]; int r = fsRead.Read(buffer, 0, buffer.Length); //获得发送的信息时候,在数组前面加上一个字节 1 List<byte> list = new List<byte>(); list.Add(1); list.AddRange(buffer); byte[] newBuffer = list.ToArray(); //将了标识字符的字节数组传递给客户端 socketSend.Send(newBuffer, 0, r + 1, SocketFlags.None); txtPath.Text = ""; } } catch{ } } /// <summary> /// 震动 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnZD_Click(object sender, EventArgs e) { try { // 首字节是2说明是震动 byte[] buffer = new byte[1]; buffer[0] = 2; socketSend.Send(buffer); } catch{ } } /// <summary> /// 震动 /// </summary> private void ZD() { //获取当前窗体的坐标 Point point = this.Location; //反复给窗体坐标复制一百次,达到震动的效果 for (int i = 0; i < 100; i++) { this.Location = new Point(point.X - 5, point.Y - 5); this.Location = new Point(point.X + 5, point.Y + 5); } this.Location = point; } } }
1)传输类型说明以及全局变量
这些说明以及全局变量,说的也比较清楚,也不累赘了。
2)Socket通信服务端具体步骤:
(这些步骤都是根据第一个图来的)
(1)建立一个通信的Socket
/// <summary> /// 建立连接 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnStart_Click(object sender, EventArgs e) { try { //创建负责通信的Socket socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //获取服务端的IP IPAddress ip = IPAddress.Parse(txtServer.Text.Trim()); //获取服务端的端口号 IPEndPoint port = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text)); //获得要连接的远程服务器应用程序的IP地址和端口号 socketSend.Connect(port); ShowMsg("连接成功"); //新建线程,去接收客户端发来的信息 Thread td = new Thread(AcceptMgs); td.IsBackground = true; td.Start(); } catch { } }
在连接按钮里,我们建立了Socket
由于客户端会不停的去监视接收服务端发来的信息,如果把这个工作放到主线程里,程序会出现假死的现象,所以这里给他放到一个新的线程里。
(2)接收信息
/// <summary> /// 接收数据 /// </summary> private void AcceptMgs() { try { /// <summary> /// 存储大文件的大小 /// </summary> long length = 0; long recive = 0; //接收的大文件总的字节数 while (true) { byte[] buffer = new byte[1024 * 1024]; int r = socketSend.Receive(buffer); if (r == 0) { break; } if (length > 0) //判断大文件是否已经保存完 { //保存接收的文件 using (FileStream fsWrite = new FileStream(filePath, FileMode.Append, FileAccess.Write)) { fsWrite.Write(buffer, 0, r); length -= r; //减去每次保存的字节数 ShowMsg(string.Format("{0}: 已接收:{1}/{2}", socketSend.RemoteEndPoint, recive-length, recive)); if (length <= 0) { ShowMsg(socketSend.RemoteEndPoint + ": 接收文件成功"); } continue; } } if (buffer[0] == 0) //如果接收的字节数组的第一个字节是0,说明接收的字符串信息 { string strMsg = Encoding.UTF8.GetString(buffer, 1, r - 1); ShowMsg(socketSend.RemoteEndPoint.ToString() + ": " + strMsg); } else if (buffer[0] == 1) //如果接收的字节数组的第一个字节是1,说明接收的是文件 { length = int.Parse(Encoding.UTF8.GetString(buffer,1,r-1)); recive = length; filePath = ""; SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "保存文件"; sfd.InitialDirectory = @"C:\Users\Administrator\Desktop"; sfd.Filter = "文本文件|*.txt|图片文件|*.jpg|视频文件|*.avi|所有文件|*.*"; //如果没有选择保存文件路径就一直打开保存框 while (true) { sfd.ShowDialog(this); filePath = sfd.FileName; if (string.IsNullOrEmpty(filePath)) { continue; } else { break; } } } else if (buffer[0] == 2) //如果接收的字节数组的第一个字节是2,说明接收的是震动 { ZD(); } } } catch { } }
接收信息是会根据接收到字节数字的第一个字节来判断接收到的是什么,如果接收的是个大文件,首先会接收大文件的大小,然后根据大小接收相同大小的字节数组追加保存到一个文件里去。
(3)发送数据(这里分发送字符串、文件(包含大文件)、震动)
发送字符串信息
/// <summary> /// 发送数据 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSend_Click(object sender, EventArgs e) { try { byte[] buffer = Encoding.UTF8.GetBytes(txtMsg.Text); //获得发送的信息时候,在数组前面加上一个字节 0 List<byte> list = new List<byte>(); list.Add(0); list.AddRange(buffer); //将泛型集合转换为数组 byte[] newBuffer = list.ToArray(); //将了标识字符的字节数组传递给客户端 socketSend.Send(newBuffer); txtMsg.Text = ""; } catch{} }
发送震动
/// <summary> /// 震动 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnZD_Click(object sender, EventArgs e) { try { // 首字节是2说明是震动 byte[] buffer = new byte[1]; buffer[0] = 2; socketSend.Send(buffer); } catch{ } } /// <summary> /// 震动 /// </summary> private void ZD() { //获取当前窗体的坐标 Point point = this.Location; //反复给窗体坐标复制一百次,达到震动的效果 for (int i = 0; i < 100; i++) { this.Location = new Point(point.X - 5, point.Y - 5); this.Location = new Point(point.X + 5, point.Y + 5); } this.Location = point; }
发送文件(不包含大文件)
首先要选择文件
/// <summary> /// 选择文件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSelect_Click(object sender, EventArgs e) { //打开文件 OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "选择要传的文件"; ofd.InitialDirectory = @"C:\Users\Administrator\Desktop"; ofd.Filter = "文本文件|*.txt|图片文件|*.jpg|视频文件|*.avi|所有文件|*.*"; ofd.ShowDialog(); //得到选择文件的路径 txtPath.Text = ofd.FileName; }
然后在发送文件
/// <summary> /// 发送文件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSendFile_Click(object sender, EventArgs e) { try { string filePath = txtPath.Text; if (string.IsNullOrEmpty(filePath)) { MessageBox.Show("请选择文件"); return; } //读取选择的文件 using (FileStream fsRead = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Read)) { byte[] buffer = new byte[1024 * 1024 * 2]; int r = fsRead.Read(buffer, 0, buffer.Length); //获得发送的信息时候,在数组前面加上一个字节 1 List<byte> list = new List<byte>(); list.Add(1); list.AddRange(buffer); byte[] newBuffer = list.ToArray(); //将了标识字符的字节数组传递给客户端 socketSend.Send(newBuffer, 0, r + 1, SocketFlags.None); txtPath.Text = ""; } } catch{ } }