使用Socket通信的服务器端编程,熟悉了服务器端和客户端的通信流程,实现了收发信息、文件传送以及震动功能
服务器端先创建Socket,然后将其和本地ip地址以及端口号连接,也就是使用Bind方法,然后使用Listen方法监听。
用Accept方法接受客户端的连接申请,并且等待客户端连接(在winform中,由于Accept方法是阻塞方法,必须创建一个线程来执行,防止主窗体卡死)
客户端连接成功Accept方法会返回一个用于发送和接收消息的Socket,之后就要用这个socket进行通信
在通信过程中要像实现不同功能,比如传送文件,就要在发送的字节流中使用一定的位置来存储信息,也就是使用自己的协议,在这个案例中,取第一个字节标识信息,0代表发送信息,1代表传递文件,2代表震动窗体
服务端代码如下
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 using System.Net.Sockets; 11 using System.Net; 12 using System.Threading; 13 using System.IO; 14 15 namespace ServerReview 16 { 17 public partial class Form1 : Form 18 { 19 public Form1() 20 { 21 InitializeComponent(); 22 } 23 private Socket socketSend; 24 private Socket socketWatch; 25 private Dictionary<string, Socket> socketClientList = new Dictionary<string, Socket>(); 26 private void btnStart_Click(object sender, EventArgs e) 27 { 28 socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 29 IPAddress ip = IPAddress.Any; 30 IPEndPoint iep = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text)); 31 //将套接字和本机地址绑定 32 socketWatch.Bind(iep); 33 ShowMsg("监听成功"); 34 //用Listen监听 35 socketWatch.Listen(10); 36 //创建新线程不停接受客户端请求 37 Thread thread = new Thread(ServerAccept); 38 thread.IsBackground = true; 39 thread.Start(); 40 } 41 private void ServerAccept() 42 { 43 while (true) 44 { 45 socketSend = socketWatch.Accept(); 46 socketClientList.Add(socketSend.RemoteEndPoint.ToString(), socketSend); 47 cboUsers.Items.Add(socketSend.RemoteEndPoint.ToString()); 48 ShowMsg(socketSend.RemoteEndPoint.ToString() + "连接成功"); 49 //开启新线程不停接收消息 50 Thread thread = new Thread(ServerReceive); 51 thread.IsBackground = true; 52 thread.Start(); 53 } 54 } 55 private void ServerReceive() 56 { 57 while (true) 58 { 59 try 60 { 61 byte[] buffer = new byte[1024 * 1024 * 2]; 62 int byteNum = socketSend.Receive(buffer); 63 if (byteNum == 0) 64 { 65 break; 66 } 67 string str = Encoding.UTF8.GetString(buffer, 0, byteNum); 68 ShowMsg(socketSend.RemoteEndPoint.ToString() + ":" + str); 69 } 70 catch { } 71 } 72 } 73 private void ShowMsg(string str) 74 { 75 txtLog.AppendText(str + " "); 76 } 77 78 private void Form1_Load(object sender, EventArgs e) 79 { 80 Control.CheckForIllegalCrossThreadCalls = false; 81 } 82 83 private void btnSend_Click(object sender, EventArgs e) 84 { 85 string str = txtMsg.Text; 86 List<byte> list = new List<byte>(); 87 list.Add(0); 88 byte[] buffer = Encoding.UTF8.GetBytes(str); 89 list.AddRange(buffer); 90 byte[] newBuffer = list.ToArray(); 91 string ip = cboUsers.SelectedItem.ToString(); 92 socketClientList[ip].Send(newBuffer); 93 } 94 95 private void btnSelectFile_Click(object sender, EventArgs e) 96 { 97 OpenFileDialog ofd = new OpenFileDialog(); 98 ofd.InitialDirectory = @"D:"; 99 ofd.Title = "请选择要发送的文件"; 100 ofd.Filter = "所有文件|*.*"; 101 ofd.ShowDialog(); 102 txtFilePath.Text = ofd.FileName; 103 } 104 105 private void btnSendFile_Click(object sender, EventArgs e) 106 { 107 string path = txtFilePath.Text; 108 using(FileStream fsRead = new FileStream(path, FileMode.Open, FileAccess.Read)) 109 { 110 try 111 { 112 byte[] buffer = new byte[1024 * 1024 * 5]; 113 int l = fsRead.Read(buffer, 0, buffer.Length); 114 List<byte> list = new List<byte>(); 115 list.Add(1); 116 list.AddRange(buffer); 117 byte[] newBuffer = list.ToArray(); 118 socketClientList[cboUsers.SelectedItem.ToString()].Send(newBuffer,0,l+1,SocketFlags.None); 119 } 120 catch { } 121 } 122 } 123 124 private void btnShake_Click(object sender, EventArgs e) 125 { 126 byte[] buffer = new byte[1]; 127 buffer[0] = 2; 128 socketClientList[cboUsers.SelectedItem.ToString()].Send(buffer); 129 } 130 } 131 }
客户端代码如下:
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 15 namespace ClientRevier 16 { 17 public partial class Form1 : Form 18 { 19 public Form1() 20 { 21 InitializeComponent(); 22 } 23 24 private void Form1_Load(object sender, EventArgs e) 25 { 26 Control.CheckForIllegalCrossThreadCalls = false; 27 } 28 private Socket socketClient; 29 private void btnStart_Click(object sender, EventArgs e) 30 { 31 socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 32 IPAddress ip = IPAddress.Parse(txtServer.Text); 33 IPEndPoint iep = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text)); 34 socketClient.Connect(iep); 35 ShowMsg("连接成功"); 36 //因为要不停接受消息,所以用while循环,并且为了接受消息的同时能做其他事,把这个放到线程中执行 37 Thread thread = new Thread(ClientRecieve); 38 thread.IsBackground = true; 39 thread.Start(); 40 } 41 private void ClientRecieve() 42 { 43 while (true) 44 { 45 byte[] buffer = new byte[1024 * 1024 * 2]; 46 int byteNum = socketClient.Receive(buffer); 47 if (byteNum == 0) 48 { 49 break; 50 } 51 switch (buffer[0]) 52 { 53 case 0: 54 string str = Encoding.UTF8.GetString(buffer, 1, byteNum-1); 55 ShowMsg(socketClient.RemoteEndPoint + ":" + str); 56 break; 57 case 1: 58 SaveFileDialog sfd = new SaveFileDialog(); 59 sfd.InitialDirectory = @"D"; 60 sfd.Title = "请选择需要保存的路径"; 61 sfd.Filter = "文本文件|*.txt|图片文件|*.jpg|所有文件|*.*"; 62 sfd.ShowDialog(this); 63 using(FileStream fsWrite = new FileStream(sfd.FileName, FileMode.OpenOrCreate, FileAccess.Write)) 64 { 65 fsWrite.Write(buffer, 1, byteNum - 1); 66 MessageBox.Show("保存成功"); 67 } 68 break; 69 case 2: 70 for(int i = 0; i < 1000; i++) 71 { 72 this.Location = new Point(200, 200); 73 this.Location = new Point(230, 230); 74 } 75 break; 76 default:break; 77 } 78 79 } 80 } 81 private void ShowMsg(string str) 82 { 83 txtLog.AppendText(str + " "); 84 } 85 86 private void btnSend_Click(object sender, EventArgs e) 87 { 88 string str = txtMsg.Text; 89 byte[] buffer = Encoding.UTF8.GetBytes(str); 90 socketClient.Send(buffer); 91 92 } 93 } 94 }