先來三個參考網站
1:介紹所需要的類別 跟Web的sample code
https://msdn.microsoft.com/zh-tw/library/dn535720.aspx?f=255&MSPPError=-2147217396
2. signalr的邏輯跟ajaxhttp需求的差異
https://blogs.msdn.microsoft.com/msdntaiwan/2013/09/09/signalr-web-web/
3.Hub上的觀念使用
http://blog.darkthread.net/post-2012-07-10-signalr-remote-controller.aspx
這東西的邏輯很特別
好像起來以後用戶跟SERVER之間開一條獨立連線一樣
會有一個專有的context.connectId 在設定的對應好的hub上產生相對應的呼叫
像在用戶端要呼叫server端的function
server端也要寫用戶端可以互相對應的function
是完全委派的方法
Server端
public partial class WinFormsServer : Form { public static int i = 0; private IDisposable SignalR { get; set; } const string ServerURI = "http://localhost:8080"; internal WinFormsServer() { InitializeComponent(); EventArgs e=new EventArgs(); ButtonStart_Click(sender,null); } private void ButtonStart_Click(object sender, EventArgs e) { WriteToConsole("Starting server..."); ButtonStart.Enabled = false; Task.Run(() => StartServer()); } private void ButtonStop_Click(object sender, EventArgs e) { Close(); } private void StartServer() { try { SignalR = WebApp.Start(ServerURI); } catch (TargetInvocationException) { WriteToConsole("Server failed to start. A server is already running on " + ServerURI); this.Invoke((Action)(() => ButtonStart.Enabled = true)); return; } this.Invoke((Action)(() => ButtonStop.Enabled = true)); WriteToConsole("Server started at " + ServerURI); } internal void WriteToConsole(String message) { if (RichTextBoxConsole.InvokeRequired) { this.Invoke((Action)(() => WriteToConsole(message) )); return; } RichTextBoxConsole.AppendText(message + Environment.NewLine); } private void WinFormsServer_FormClosing(object sender, FormClosingEventArgs e) { if (SignalR != null) { SignalR.Dispose(); } } } class Startup { public void Configuration(IAppBuilder app) { app.UseCors(CorsOptions.AllowAll); app.MapSignalR(); } } public class UserInfo { public string ContextID { get; set; } public string Name { get; set; } } public class MyHub : Hub { private void GetUserList() { var itme = from a in UserList select new { a.Name, a.ContextID }; string jsondata = JsonConvert.SerializeObject(itme.ToList()); Clients.All.getUserlist(jsondata); } public void Send(string name, string message) { var user = UserList.Where(u => u.Name == name).FirstOrDefault(); var userSend = UserList.Where(u => u.ContextID == Context.ConnectionId).FirstOrDefault(); Clients.Client(user.ContextID).addMessage(" User:" + userSend.Name + ":" + message + " " + DateTime.Now, " User:" + userSend.Name + " Id:"+ Context.ConnectionId); } public void SendAllUser() { var userSend = UserList.Where(u => u.ContextID == Context.ConnectionId).FirstOrDefault(); foreach (var users in UserList) { Clients.All.addMessageUser(users.ContextID, users.Name); } } public void GetUserInfo() { foreach (var users in UserList) { Clients.All.addMessageUser(users.ContextID, users.Name); } } public static List<UserInfo> UserList = new List<UserInfo>(); public override Task OnConnected() { var user = UserList.SingleOrDefault(u => u.ContextID == Context.ConnectionId); if (user == null) { user = new UserInfo() { Name = "User"+i, ContextID = Context.ConnectionId }; UserList.Add(user); i++; } Program.MainForm.WriteToConsole("Client connected: " + Context.ConnectionId); return base.OnConnected(); } public override Task OnDisconnected() { var user = UserList.SingleOrDefault(u => u.ContextID == Context.ConnectionId); Clients.All.DeleteMessageUser(user.Name); UserList.Remove(user); Program.MainForm.WriteToConsole("Client disconnected: " + Context.ConnectionId); return base.OnDisconnected(); } }
用戶端
public partial class WinFormsClient : Form { private String UserName { get; set; } private IHubProxy HubProxy { get; set; } const string ServerURI = "http://localhost:8080"; private HubConnection Connection { get; set; } internal WinFormsClient() { InitializeComponent(); EventArgs e=new EventArgs(); object sender = new object(); SignInButton_Click(sender,e); } private void ButtonSend_Click(object sender, EventArgs e) { if (listBox1.SelectedItem != null) { HubProxy.Invoke("Send", listBox1.SelectedItem.ToString(), TextBoxMessage.Text); TextBoxMessage.Text = String.Empty; TextBoxMessage.Focus(); } } private async void ConnectAsync() { Connection = new HubConnection(ServerURI); Connection.Closed += Connection_Closed; HubProxy = Connection.CreateHubProxy("MyHub"); HubProxy.On<string, string>("AddMessage", (message, messageUserInfo) => this.Invoke((Action)(() => RichTextBoxConsole.AppendText(String.Format("{0}: {1}" + Environment.NewLine, message, messageUserInfo)) )) ); HubProxy.On<string, string>("AddMessageUser", (name, message) => this.Invoke((Action)(() => MakeUserList(name, message) )) ); HubProxy.On<string>("DeleteMessageUser", (name) => this.Invoke((Action)(() => DeleteUserList(name) )) ); try { await Connection.Start(); } catch (HttpRequestException) { StatusText.Text = "Unable to connect to server: Start server before connecting clients."; return; } //Activate UI SignInPanel.Visible = false; ChatPanel.Visible = true; ButtonSend.Enabled = true; TextBoxMessage.Focus(); RichTextBoxConsole.AppendText("Connected to server at " + ServerURI + Environment.NewLine); EventArgs e = new EventArgs(); object sender = new object(); button1_Click(sender, e); } private void DeleteUserList(string name) { if (listBox1.Items.Contains(name)) { listBox1.Items.Remove(name); } } private void MakeUserList(string name, string message) { RichTextBoxConsoleAll.AppendText(String.Format("{0}: {1}" + Environment.NewLine, name, message)); if (!listBox1.Items.Contains(message)) { listBox1.Items.AddRange(new object[] {message}); } } private void Connection_Closed() { this.Invoke((Action)(() => ChatPanel.Visible = false)); this.Invoke((Action)(() => ButtonSend.Enabled = false)); this.Invoke((Action)(() => StatusText.Text = "You have been disconnected.")); this.Invoke((Action)(() => SignInPanel.Visible = true)); } private void SignInButton_Click(object sender, EventArgs e) { UserName = UserNameTextBox.Text; { StatusText.Visible = true; StatusText.Text = "Connecting to server..."; ConnectAsync(); } } private void WinFormsClient_FormClosing(object sender, FormClosingEventArgs e) { if (Connection != null) { Connection.Stop(); Connection.Dispose(); } } private void button1_Click(object sender, EventArgs e) { HubProxy.Invoke("SendAllUser"); TextBoxMessage.Text = String.Empty; TextBoxMessage.Focus(); HubProxy.Invoke("GetUserInfo"); } }
如兩圖所示 一邊適用 HubProxy.Invoke("SendAllUser");
呼叫server的funcion
server也用 Client.All方法 打回給user user再用
HubProxy.On<string, string>("AddMessageUser", (name, message) =>
this.Invoke((Action)(() =>
MakeUserList(name, message)
))
);
指定client端要跑 MakeUserList(name, message)這個function
就整體來說 挺好玩的 也減少SERVER跟CLIENT的負擔 跟傳輸資料量