image.png
    自己定制一个协议
    image.png

    Server:
    image.png

    1. using System;
    2. using System.Collections.Generic;
    3. using System.ComponentModel;
    4. using System.Data;
    5. using System.Drawing;
    6. using System.IO;
    7. using System.Linq;
    8. using System.Net;
    9. using System.Net.Sockets;
    10. using System.Text;
    11. using System.Threading;
    12. using System.Threading.Tasks;
    13. using System.Windows.Forms;
    14. namespace _123_服务器与客户端交互_聊天_Server
    15. {
    16. public partial class FormServer : Form
    17. {
    18. public FormServer()
    19. {
    20. InitializeComponent();
    21. }
    22. /// <summary>
    23. /// 点击按钮开始监听
    24. /// </summary>
    25. /// <param name="sender"></param>
    26. /// <param name="e"></param>
    27. private void btnStart_Click(object sender, EventArgs e)
    28. {
    29. try
    30. {
    31. //创建一个负责监听(服务器IP地址和端口号)的Socket // 网络协议IP V4版本 流式使用TCP协议
    32. Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    33. //创建IP地址和端口号对象
    34. IPAddress ip = IPAddress.Any; //客户端的活动地址,可变 //IPAddress.Parse(txtServer.Text);这样子只会把txtServer.Text作为IP地址不可变。
    35. IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
    36. //让负责监听的Socket绑定IP地址和端口号
    37. socketWatch.Bind(point);
    38. ShowMsg("监听成功");
    39. //设置监听队列
    40. socketWatch.Listen(10);//在某一时间点内最大容量
    41. Thread th = new Thread(Listen);
    42. th.IsBackground = true;
    43. th.Start(socketWatch);
    44. }
    45. catch
    46. {
    47. MessageBox.Show("Server项目的(btnStart_Click())可能出问题了,请找大师。");
    48. }
    49. }
    50. /// <summary>
    51. /// 将字符串显示在Log文本框中
    52. /// </summary>
    53. /// <param name="str">即将要显示的字符串</param>
    54. public void ShowMsg(string str)
    55. {
    56. txtLog.AppendText(str + "\r\n");
    57. }
    58. //将远程连接的客户端IP地址和Socket存入集合中
    59. Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();
    60. //创建跟客户端通信的Socket类的变量
    61. Socket socketSend;
    62. /// <summary>
    63. /// 等待客户端的连接,并且创建与之通信的Socket
    64. /// </summary>
    65. public void Listen(object o)
    66. {
    67. Socket socketWatch = o as Socket;
    68. while (true)
    69. {
    70. try
    71. {
    72. //负责监听的Socket 来接受客户端的连接(等待客户端连接) 并且创建跟客户端通信的Socket
    73. //负责和客户端通信的Socket
    74. socketSend = socketWatch.Accept();
    75. //将此时客户端ip和SocketSend存入
    76. dicSocket.Add(socketSend.RemoteEndPoint.ToString(), socketSend);
    77. //将此时客户端的ip地址和端口号存入下拉框中
    78. cboUsers.Items.Add(socketSend.RemoteEndPoint.ToString());
    79. //将谁(远程终结点)连接显示在文本框内
    80. ShowMsg(socketSend.RemoteEndPoint.ToString() + ":连接成功");//获取远程终结点
    81. //开启一个新线程,不停地接受客户端发来的消息
    82. Thread th = new Thread(Receive);
    83. th.IsBackground = true;
    84. th.Start(socketSend);
    85. }
    86. catch
    87. {
    88. MessageBox.Show("Server项目的(Listen())可能出问题了,请找大师。");
    89. }
    90. }
    91. }
    92. /// <summary>
    93. /// 服务器端不停地接受客户端发来的消息
    94. /// </summary>
    95. /// <param name="o"></param>
    96. public void Receive(object o)
    97. {
    98. Socket socketSend = o as Socket;
    99. while (true)
    100. {
    101. try
    102. {
    103. //客户端连接成功后,服务器应该接受客户端发来的消息
    104. byte[] buffer = new byte[1024 * 1024 * 2];
    105. //实际接收到的有限字节数
    106. int r = socketSend.Receive(buffer);
    107. if (r == 0)
    108. {
    109. break;
    110. }
    111. string input = Encoding.UTF8.GetString(buffer, 0, r);
    112. //显示客户端发送的数据
    113. ShowMsg(DateTime.Now + "\r\n" + socketSend.RemoteEndPoint + ":" + input);
    114. }
    115. catch
    116. {
    117. //
    118. MessageBox.Show("Server项目的(Receive())可能出问题了,请找大师。");
    119. }
    120. }
    121. }
    122. /// <summary>
    123. /// 取消不可跨线程访问
    124. /// </summary>
    125. /// <param name="sender"></param>
    126. /// <param name="e"></param>
    127. private void FormServer_Load(object sender, EventArgs e)
    128. {
    129. //取消不可跨线程访问
    130. Control.CheckForIllegalCrossThreadCalls = false;
    131. }
    132. private void FormServer_DoubleClick(object sender, EventArgs e)
    133. {
    134. ////当你点击关闭窗口的时候,判断线程是否为null
    135. //if (th != null)
    136. //{
    137. // //th.Abort();//线程被Abort后就不能被Start了
    138. // th = null;
    139. //}
    140. }
    141. /// <summary>
    142. /// 服务器给客户端发送消息
    143. /// </summary>
    144. /// <param name="sender"></param>
    145. /// <param name="e"></param>
    146. private void btnSend_Click(object sender, EventArgs e)
    147. {
    148. string input = txtMsg.Text.Trim();
    149. byte[] buffer = Encoding.UTF8.GetBytes(input);
    150. //制定协议 字节数组第一位为0:文本消息 1:文件 2:震动
    151. List<byte> list = new List<byte>();
    152. list.Add(0);//给第一位赋值为0
    153. list.AddRange(buffer);
    154. //将泛型集合穿换成数组
    155. byte[] newBuffer = list.ToArray(); //buffer = list.ToArray();不可以 数组长度不一样了
    156. //获得用户在下拉框中选中的IP地址
    157. string ip = cboUsers.SelectedItem.ToString();
    158. dicSocket[ip].Send(newBuffer);
    159. //socketSend.Send(buffer);
    160. //发送成功后清除当前文本
    161. txtMsg.Clear();
    162. txtMsg.Focus();
    163. }
    164. private void btnSelect_Click(object sender, EventArgs e)
    165. {
    166. OpenFileDialog ofd = new OpenFileDialog();
    167. ofd.Title = "客官,请选择你要发送的文件";
    168. ofd.InitialDirectory = @"C:\Users\46124\Desktop";
    169. ofd.Filter = "文本文件|*.txt|媒体文件|*.wav|媒体文件|*.mp4|所有文件|*.*";
    170. ofd.ShowDialog();
    171. //将对话框选择的文件的全路径放入文本框中
    172. txtPath.Text = ofd.FileName;
    173. }
    174. /// <summary>
    175. /// 点击发送文件
    176. /// </summary>
    177. /// <param name="sender"></param>
    178. /// <param name="e"></param>
    179. private void btnSendFile_Click(object sender, EventArgs e)
    180. {
    181. //获得要发送文件的路径
    182. string path = txtPath.Text;
    183. using (FileStream fsRead = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Read))
    184. {
    185. byte[] buffer = new byte[1024 * 1024 * 5];
    186. int r = fsRead.Read(buffer, 0, buffer.Length);
    187. //制定协议 字节数组第一位为0:文本消息 1:文件 2:震动
    188. List<byte> list = new List<byte>();
    189. list.Add(1);
    190. list.AddRange(buffer);
    191. byte[] newBuffer = list.ToArray();
    192. //通过下拉框获取需要发送客户端的IP然后发送字节数组
    193. dicSocket[cboUsers.SelectedItem.ToString()].Send(newBuffer);
    194. MessageBox.Show("发送成功");
    195. }
    196. }
    197. /// <summary>
    198. /// 发送振动
    199. /// </summary>
    200. /// <param name="sender"></param>
    201. /// <param name="e"></param>
    202. private void btnVibrate_Click(object sender, EventArgs e)
    203. {
    204. byte[] buffer = new byte[1];
    205. buffer[0] = 2;
    206. //通过下拉框获取需要发送客户端的IP然后发送字节数组
    207. dicSocket[cboUsers.SelectedItem.ToString()].Send(buffer);
    208. }
    209. private void btnClose_Click(object sender, EventArgs e)
    210. {
    211. this.Close();
    212. }
    213. }
    214. }

    Client:
    image.png

    1. using System;
    2. using System.Collections.Generic;
    3. using System.ComponentModel;
    4. using System.Data;
    5. using System.Drawing;
    6. using System.IO;
    7. using System.Linq;
    8. using System.Net;
    9. using System.Net.Sockets;
    10. using System.Text;
    11. using System.Threading;
    12. using System.Threading.Tasks;
    13. using System.Windows.Forms;
    14. namespace _124_服务器与客户端交互_聊天_Client
    15. {
    16. public partial class FormClient : Form
    17. {
    18. public FormClient()
    19. {
    20. InitializeComponent();
    21. }
    22. Socket socketSend;
    23. private void button1_Click(object sender, EventArgs e)
    24. {
    25. try
    26. {
    27. //创建负责通信的Socket
    28. socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    29. //创建IP和端口号连接服务器
    30. IPAddress ip = IPAddress.Parse(txtServer.Text);
    31. IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
    32. //获得要连接的远程服务器应用程序的IP地址和端口号
    33. socketSend.Connect(point);
    34. ShowMsg("连接成功");
    35. //开启一个新的线程不停地接受服务器发送来的消息
    36. Thread th = new Thread(Receive);
    37. th.IsBackground = true;
    38. th.Start();
    39. }
    40. catch
    41. {
    42. MessageBox.Show("连接服务器时出错,请找大师");
    43. }
    44. }
    45. /// <summary>
    46. /// 将字符串显示在Log文本框中
    47. /// </summary>
    48. /// <param name="str">即将要显示的字符串</param>
    49. public void ShowMsg(string str)
    50. {
    51. txtLog.AppendText(str + "\r\n");
    52. }
    53. /// <summary>
    54. /// 客户端给服务器发送消息
    55. /// </summary>
    56. /// <param name="sender"></param>
    57. /// <param name="e"></param>
    58. private void btnSend_Click(object sender, EventArgs e)
    59. {
    60. //将客户端发送的数据string转化成byte发送
    61. string input = txtMsg.Text.Trim();
    62. byte[] buffer = Encoding.UTF8.GetBytes(input);
    63. socketSend.Send(buffer);
    64. //发送成功后清除当前文本
    65. txtMsg.Clear();
    66. txtMsg.Focus();
    67. }
    68. /// <summary>
    69. /// 不停的接受服务器发来的消息
    70. /// </summary>
    71. public void Receive()
    72. {
    73. try
    74. {
    75. while (true)
    76. {
    77. byte[] buffer = new byte[1024 * 1024 * 2];
    78. int r = socketSend.Receive(buffer);
    79. if (r == 0)
    80. {
    81. break;
    82. }
    83. //使用协议判断字节数组第一位 0:文本消息 1:文件 2:震动
    84. if (buffer[0] == 0)
    85. {
    86. string input = Encoding.UTF8.GetString(buffer, 1, r - 1); //r-1是因为数组加了一位 数量多了一个
    87. ShowMsg(DateTime.Now + "\r\n" + socketSend.RemoteEndPoint + ":" + input);
    88. }
    89. else if (buffer[0] == 1)
    90. {
    91. SaveFileDialog sfd = new SaveFileDialog();
    92. sfd.InitialDirectory = @"C:\Users\46124\Desktop";
    93. sfd.Title = "客官,请选择保存文件的地址";
    94. sfd.Filter = "文本文件|*.txt|媒体文件|*.wav|媒体文件|*.mp4|所有文件|*.*";
    95. sfd.ShowDialog(this);
    96. string path = sfd.FileName;
    97. using (FileStream fsWrite = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
    98. {
    99. fsWrite.Write(buffer, 1, r - 1);
    100. MessageBox.Show("接受成功");
    101. }
    102. }
    103. else if (buffer[0] == 2)
    104. {
    105. Vibrate();
    106. }
    107. }
    108. }
    109. catch
    110. {
    111. MessageBox.Show("(Client项目的Receive())可能出问题了,请找大师。");
    112. }
    113. }
    114. private void FormClient_Load(object sender, EventArgs e)
    115. {
    116. Control.CheckForIllegalCrossThreadCalls = false;
    117. }
    118. /// <summary>
    119. /// 振动
    120. /// </summary>
    121. public void Vibrate()
    122. {
    123. for (int i = 0; i < 2000; i++)
    124. {
    125. //Random r = new Random();
    126. //int rNumber = r.Next(100, 250);
    127. //this.Location = new Point(this.Location.X + rNumber, this.Location.Y + rNumber);
    128. this.Location = new Point(200, 200);
    129. this.Location = new Point(300, 300);
    130. }
    131. }
    132. }
    133. }