常用的 WinForm 程序
2011-11-25 20:49 音乐让我说 阅读(309) 评论(0) 收藏 举报
1. 利用 Windows Forms 创建自动登录程序
1. 新建一个 Windows Forms 应用程序。
2. 拖一个 Panel,再向该 Panel 中拖一个 Label、TextBox、Button。设置 Panel 的 Dock 属性为 Top,其中 Top 就是固定在窗口的头部。设置 TextBox 的 Text = http://passport.cnblogs.com/login.aspx。
3. 再拖一个 Panel,再向该 Panel 中拖一个 WebBrowser,设置 Panel 和 WebBrowser 的 Dock 属性为 Fill,其中 Fill 就是全屏。再设置 WebBrowser 的 Url = "http://www.cnblogs.com/"。

4. 在后台代码中编写下面的代码:
private void button1_Click(object sender, EventArgs e) { string sUrl = this.txtUrl.Text.Trim(); if (sUrl.Length > 0) { webBrowser1.Navigate(sUrl); } } private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { if (e.Url.ToString().ToLower().IndexOf("login.aspx") == -1) { return; } HtmlElement clickBtn = null; HtmlDocument doc = webBrowser1.Document; for (int i = 0; i < doc.All.Count; i++) { if (!doc.All[i].TagName.ToUpper().Equals("INPUT")) { continue; } switch (doc.All[i].Name) { case "tbUserName": doc.All[i].InnerText = "xxxxxx"; // 用户名 break; case "tbPassword": doc.All[i].InnerText = "123456"; // 密码 break; case "btnLogin": clickBtn = doc.All[i]; break; } } if (clickBtn != null) { clickBtn.InvokeMember("click"); // 点击“登录”按钮 } }
5. 点击“登录”按钮运行。
附录:Partial 类中的代码如下:
partial class AutoLogin { /// <summary> /// 必需的设计器变量。 /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// 清理所有正在使用的资源。 /// </summary> /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows 窗体设计器生成的代码 /// <summary> /// 设计器支持所需的方法 - 不要 /// 使用代码编辑器修改此方法的内容。 /// </summary> private void InitializeComponent() { this.lblUrl = new System.Windows.Forms.Label(); this.txtUrl = new System.Windows.Forms.TextBox(); this.button1 = new System.Windows.Forms.Button(); this.webBrowser1 = new System.Windows.Forms.WebBrowser(); this.panel1 = new System.Windows.Forms.Panel(); this.panel2 = new System.Windows.Forms.Panel(); this.panel1.SuspendLayout(); this.panel2.SuspendLayout(); this.SuspendLayout(); // // lblUrl // this.lblUrl.AutoSize = true; this.lblUrl.Location = new System.Drawing.Point(3, 31); this.lblUrl.Name = "lblUrl"; this.lblUrl.Size = new System.Drawing.Size(77, 12); this.lblUrl.TabIndex = 0; this.lblUrl.Text = "请输入地址:"; // // txtUrl // this.txtUrl.Location = new System.Drawing.Point(86, 22); this.txtUrl.Name = "txtUrl"; this.txtUrl.Size = new System.Drawing.Size(342, 21); this.txtUrl.TabIndex = 1; this.txtUrl.Text = "http://passport.cnblogs.com/login.aspx"; // // button1 // this.button1.Location = new System.Drawing.Point(446, 20); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(75, 23); this.button1.TabIndex = 2; this.button1.Text = "登录"; this.button1.UseVisualStyleBackColor = true; this.button1.Click += new System.EventHandler(this.button1_Click); // // webBrowser1 // this.webBrowser1.Dock = System.Windows.Forms.DockStyle.Fill; this.webBrowser1.Location = new System.Drawing.Point(0, 0); this.webBrowser1.Margin = new System.Windows.Forms.Padding(0); this.webBrowser1.MinimumSize = new System.Drawing.Size(20, 20); this.webBrowser1.Name = "webBrowser1"; this.webBrowser1.Size = new System.Drawing.Size(600, 321); this.webBrowser1.TabIndex = 3; this.webBrowser1.Url = new System.Uri("http://www.cnblogs.com/", System.UriKind.Absolute); this.webBrowser1.DocumentCompleted += new System.Windows.Forms.WebBrowserDocumentCompletedEventHandler(this.webBrowser1_DocumentCompleted); // // panel1 // this.panel1.Controls.Add(this.lblUrl); this.panel1.Controls.Add(this.txtUrl); this.panel1.Controls.Add(this.button1); this.panel1.Dock = System.Windows.Forms.DockStyle.Top; this.panel1.Location = new System.Drawing.Point(0, 0); this.panel1.Name = "panel1"; this.panel1.Size = new System.Drawing.Size(600, 67); this.panel1.TabIndex = 4; // // panel2 // this.panel2.Controls.Add(this.webBrowser1); this.panel2.Dock = System.Windows.Forms.DockStyle.Fill; this.panel2.Location = new System.Drawing.Point(0, 67); this.panel2.Name = "panel2"; this.panel2.Size = new System.Drawing.Size(600, 321); this.panel2.TabIndex = 5; // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoSize = true; this.ClientSize = new System.Drawing.Size(600, 388); this.Controls.Add(this.panel2); this.Controls.Add(this.panel1); this.Name = "Form1"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "自动登录程序"; this.panel1.ResumeLayout(false); this.panel1.PerformLayout(); this.panel2.ResumeLayout(false); this.ResumeLayout(false); } #endregion private System.Windows.Forms.Label lblUrl; private System.Windows.Forms.TextBox txtUrl; private System.Windows.Forms.Button button1; private System.Windows.Forms.WebBrowser webBrowser1; private System.Windows.Forms.Panel panel1; private System.Windows.Forms.Panel panel2; }
2. TCP 客户端帮助类
1.
using System; namespace Utility.Comm { public interface IComm { event Action Connected; event Action Disconnected; event Action<byte[]> Received; void Start(); void Stop(); bool IsStarted { get; } bool IsConnected { get; } void Send(byte[] data); } }
2.
using System; using System.Diagnostics; using System.Linq; using System.Net; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; namespace Utility.Comm.Tcp { public class TcpClient : IComm { public event Action Connected; public event Action Disconnected; public event Action<byte[]> Received; private readonly object sync = new object(); private Socket socket; private bool isStarted; private IPEndPoint _endPoint; private bool stop; private const int ReceiveBufferSize = 1024; private readonly byte[] receiveBuffer = new byte[ReceiveBufferSize]; public string ServerAddress { get; private set; } public int ServerPort { get; private set; } public TcpClient(string serverAddress, int serverPort) { ServerAddress = serverAddress; ServerPort = serverPort; } public void Start() { if (IsStarted) return; lock (sync) stop = false; IsStarted = true; Dns.BeginGetHostAddresses(ServerAddress, GetHostAddressesCallback, null); } public virtual void Stop() { if (!IsStarted) return; lock (sync) { stop = true; _endPoint = null; if (socket != null) { if (socket.Connected) { RaiseDisconnected(); } socket.Close(); socket = null; } } IsStarted = false; } public bool IsStarted { get { return isStarted; } protected set { if (isStarted.Equals(value)) { return; } isStarted = value; var logger = NLog.LogManager.GetCurrentClassLogger(); if (isStarted) logger.Info("{0} Started : {1}:{2}", GetType().Name, ServerAddress, ServerPort); else logger.Info("{0} Stopped", GetType().Name); } } public bool IsConnected { get { lock(sync) return socket != null && socket.Connected; } } public void Send(byte[] message) { try { lock (sync) { if (stop || socket == null || !socket.Connected) { return; } socket.Send(message); } } catch (SocketException ex) { if (ex.ErrorCode == 10054) { // 10054 == An existing connection was forcibly closed by the remote host // Expected when a remote client disconnects. ServerDisconnected(); return; } NLog.LogManager.GetCurrentClassLogger() .ErrorException(string.Format("Send : SocketException : {0} : {1}", ex.ErrorCode, ex.Message), ex); } catch (Exception ex) { NLog.LogManager.GetCurrentClassLogger() .ErrorException(string.Format("Send : {0} : {1}", ex.GetType(), ex.Message), ex); } } private void GetHostAddressesCallback(IAsyncResult ar) { try { lock (sync) if (stop) return; var ipAddresses = Dns.EndGetHostAddresses(ar); var serverIpAddress = ipAddresses.FirstOrDefault(ipAddress => ipAddress.AddressFamily == AddressFamily.InterNetwork); if(serverIpAddress == null) throw new Exception(string.Format("Could not resolve server address '{0}'", ServerAddress)); _endPoint = new IPEndPoint(serverIpAddress, ServerPort); lock (sync) { socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.BeginConnect(_endPoint, ConnectCallback, null); } } catch (Exception ex) { NLog.LogManager.GetCurrentClassLogger().WarnException(string.Format("GetHostAddressesCallback : {0} : {1}", ex.GetType(), ex.Message), ex); Thread.Sleep(2000); lock (sync) if (stop) return; Dns.BeginGetHostAddresses(ServerAddress, GetHostAddressesCallback, null); } } private void ConnectCallback(IAsyncResult ar) { try { lock (sync) { if (stop) return; socket.EndConnect(ar); RaiseConnected(); SocketError receiveError; socket.BeginReceive(receiveBuffer, 0, ReceiveBufferSize, SocketFlags.None, out receiveError, ReceiveCallback, null); } } catch (SocketException ex) { NLog.LogManager.GetCurrentClassLogger().WarnException(string.Format("ConnectCallback : SocketException : {0} : {1}", ex.ErrorCode, ex.Message), ex); Thread.Sleep(2000); lock (sync) { if (stop) return; socket.BeginConnect(_endPoint, ConnectCallback, null); } } catch (Exception ex) { NLog.LogManager.GetCurrentClassLogger().WarnException(string.Format("ConnectCallback : {0} : {1}", ex.GetType(), ex.Message), ex); Thread.Sleep(2000); lock (sync) { if (stop) return; socket.BeginConnect(_endPoint, ConnectCallback, ar.AsyncState); } } } private void ReceiveCallback(IAsyncResult ar) { var logger = NLog.LogManager.GetCurrentClassLogger(); try { int received; lock (sync) { if (stop) return; received = socket.EndReceive(ar); if (received == 0) { if (stop) return; ServerDisconnected(); } } var buffer = new byte[received]; Buffer.BlockCopy(receiveBuffer, 0, buffer, 0, received); RaiseReceived(buffer); lock (sync) { if (stop) return; SocketError receiveError; socket.BeginReceive(receiveBuffer, 0, ReceiveBufferSize, SocketFlags.None, out receiveError, ReceiveCallback, null); } } catch (SocketException ex) { if (ex.ErrorCode == 10054 || ex.ErrorCode == 10060) { // 10054 == An existing connection was forcibly closed by the remote host // 10060 == An established connection failed because connected host has failed to respond // Expected when a remote client disconnects. ServerDisconnected(); return; } logger.ErrorException(string.Format("ReceiveCallback : SocketException : {0} : {1}", ex.ErrorCode, ex.Message), ex); lock (sync) if (stop) return; } catch (Exception ex) { lock (sync) if (stop) return; logger.ErrorException(string.Format("ReceiveCallback : {0} : {1}", ex.GetType(), ex.Message), ex); } } private void ServerDisconnected() { lock (sync) { if (stop) return; if (socket.Connected) { socket.Disconnect(true); } RaiseDisconnected(); socket.BeginConnect(_endPoint, ConnectCallback, null); } } private void RaiseConnected() { //NLog.LogManager.GetCurrentClassLogger().Info("{0} Connected : {1}:{2}", GetType().Name, ServerAddress, ServerPort); if (Connected != null) { Connected(); } } private void RaiseDisconnected() { //NLog.LogManager.GetCurrentClassLogger().Info("{0} Disconnected : {1}:{2}", GetType().Name, ServerAddress, ServerPort); if (Disconnected != null) { Disconnected(); } } private void RaiseReceived(byte[] data) { //NLog.LogManager.GetCurrentClassLogger().Info("{0} Received : {1}:{2}", GetType().Name, ServerAddress, ServerPort); if (Received != null) { Received(data); } } } }
3. TCPHelpers
服务端:
using System; using System.Collections.Generic; using System.Text; using System.Net.Sockets; using System.Net; using System.Threading; namespace ConnectionServer { class Program { /// <summary> /// This lock is used for console output to avoid several clients writing at the same time. /// </summary> private static object serverLock = new object(); /// <summary> /// Enable/disable console output /// </summary> private static bool showText = true; /// <summary> /// Server listen port /// </summary> private static int port; /// <summary> /// Server listen socket /// </summary> private static Socket serverSocket; /// <summary> /// Client socket and it's receive buffer /// </summary> private class ConnectionInfo { public Socket Socket; public byte[] Buffer; } private static List<ConnectionInfo> connections = new List<ConnectionInfo>(); /// <summary> /// Initializes server socket which will listen to new connections /// </summary> private static void SetupServerSocket() { IPEndPoint myEndpoint = new IPEndPoint( IPAddress.Any, port); // Create the socket, bind it, and start listening serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); serverSocket.Blocking = false; serverSocket.Bind(myEndpoint); serverSocket.Listen((int)SocketOptionName.MaxConnections); } public static void Start() { Console.Write("Starting TCP server... "); try { SetupServerSocket(); // you can accept multiple incomming connections at single time for (int i = 0; i < 10; i++) serverSocket.BeginAccept( new AsyncCallback(AcceptCallback), serverSocket); } catch (Exception e) { Console.WriteLine("Fail."); Console.WriteLine(e); } Console.WriteLine("Done. Listening."); } /// <summary> /// On accept, this callback is called from unknown system thread. /// </summary> /// <param name="result"></param> private static void AcceptCallback(IAsyncResult result) { Console.WriteLine("Accept!"); // create new connection info to store new connection information (in this case just socket/buffer) ConnectionInfo connection = new ConnectionInfo(); try { // Finish Accept Socket s = (Socket)result.AsyncState; connection.Socket = s.EndAccept(result); connection.Socket.Blocking = false; connection.Buffer = new byte[255]; lock (connections) connections.Add(connection); Console.WriteLine("New connection from " + s); // Start Receive connection.Socket.BeginReceive(connection.Buffer, 0, connection.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), connection); // Start new Accept, accept other connections serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), result.AsyncState); } catch (SocketException exc) { CloseConnection(connection); Console.WriteLine("Socket exception: " + exc.SocketErrorCode); } catch (Exception exc) { CloseConnection(connection); Console.WriteLine("Exception: " + exc); } } /// <summary> /// On receive, this callback is called from unknown system thread. /// </summary> /// <param name="result"></param> private static void ReceiveCallback(IAsyncResult result) { ConnectionInfo connection = (ConnectionInfo)result.AsyncState; try { int bytesRead = connection.Socket.EndReceive(result); if (0 != bytesRead) { // note that this "serverLock" is just for outputing to console. // otherwise no locks would be needed if this method did its work // in isolated way lock (serverLock) { if (showText) { string text = Encoding.UTF8.GetString(connection.Buffer, 0, bytesRead); Console.Write(text); } } // if we needed send simple response to the same socket, this would suffice: // connection.Socket.Send(connection.Buffer, bytesRead, SocketFlags.None); // however, this code sends the same received data to all other connected clients // so we protect connections wile we are iterating over them // to avoid any other thread removing/adding sockets while iteration // is in progress lock (connections) { foreach (ConnectionInfo conn in connections) { if (connection != conn) { conn.Socket.Send(connection.Buffer, bytesRead, SocketFlags.None); } } } // begin receive additional data connection.Socket.BeginReceive(connection.Buffer, 0, connection.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), connection); } else CloseConnection(connection); } catch (SocketException) { CloseConnection(connection); } catch (Exception) { CloseConnection(connection); } } private static void CloseConnection(ConnectionInfo ci) { ci.Socket.Close(); lock (connections) { connections.Remove(ci); Console.WriteLine(string.Format("Clients: {0}", connections.Count)); } } static void Main(string[] args) { Console.WriteLine("TCP listener and proxy. Default mode is \"text\"."); Console.WriteLine(); Console.WriteLine("|--- \"exit\" to exit. ---|"); Console.WriteLine("|--- \"show text\" to display tcp data as text. ---|"); Console.WriteLine("|--- \"hide text\" to stop displaying tcp data as text. ---|"); Console.WriteLine("|--- \"drop all\" to drop all connections. ---|"); Console.WriteLine(); Console.Write("Please enter listen port number: "); bool portReady = false; string line = Console.ReadLine(); while (line != "exit") { if (!portReady) { try { port = int.Parse(line); if (port > short.MaxValue || port < 2) { Console.WriteLine("Invalid port number."); Console.Write("Please enter port number: "); } else { Start(); portReady = true; } } catch { Console.WriteLine("Invalid port number."); Console.Write("Please enter port number: "); } } else { if (line == "show text") { lock (serverLock) { if (showText == false) { showText = true; Console.WriteLine("Text output enabled."); } } } else if (line == "hide text") { lock (serverLock) { if (showText == true) { showText = false; Console.WriteLine("Text output disabled."); } } } else if (line == "drop all") { lock (connections) { for (int i = connections.Count - 1; i >= 0; i--) { CloseConnection(connections[i]); } } } else { // send entered data to all clients lock (connections) { foreach (ConnectionInfo conn in connections) { byte[] bytes = Encoding.UTF8.GetBytes(line + "\n"); conn.Socket.Send(bytes, bytes.Length, SocketFlags.None); } } } } line = Console.ReadLine(); } Console.Write("Shutting down server... "); lock (connections) { for (int i = connections.Count - 1; i >= 0; i--) { CloseConnection(connections[i]); } } Console.WriteLine("Bye."); Thread.Sleep(500); } } }
客户端:
using System; using System.Collections.Generic; using System.Text; using System.Threading; using System.Net.Sockets; using System.Net; namespace ConnectionClient { public class SocketInfo { /// <summary> /// Socket receive buffer /// </summary> public byte[] buffer = new byte[255]; /// <summary> /// Socket itself /// </summary> public Socket socket = null; } class Program { /* server info */ private static string address; private static int port; private static IPEndPoint clientEndpoint; /// <summary> /// List of sockets, because this test client can spam the same server from multiple /// connections /// </summary> private static List<SocketInfo> socketList = new List<SocketInfo>(); static void Start() { // Create socket based on stored server info (always connecting to the same server in this app) Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // store socket buffer together with socket in the same class SocketInfo info = new SocketInfo(); info.socket = clientSocket; // when accessing socket list, always lock it. // if we had no need to so any action with all the sockets, we could do away // without locks lock (socketList) { socketList.Add(info); } Console.Write("Connecting... "); try { info.socket.Connect(clientEndpoint); Console.WriteLine("Done."); // begin receiving data. We pass SocketInfo over "state" argument // to avoid concurency issues, because ReceiveCallback will be called from unknown thread info.socket.BeginReceive(info.buffer, 0, info.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), info); } catch (Exception e) { lock (socketList) { socketList.Remove(info); } Console.WriteLine("Fail."); Console.WriteLine(e); } } /// <summary> /// Receive callback is called from unknown system thread /// </summary> /// <param name="result"></param> static void ReceiveCallback(IAsyncResult result) { SocketInfo info = (SocketInfo)result.AsyncState; try { // have to call this to notify that we have received data int bytestoread = info.socket.EndReceive(result); if (bytestoread > 0) { // in this case we are outputing data stream directly into console string text = Encoding.UTF8.GetString(info.buffer, 0, bytestoread); Console.Write(text); // begin receive again, note how we don't need any locks! info.socket.BeginReceive(info.buffer, 0, 255, SocketFlags.None, new AsyncCallback(ReceiveCallback), info); } else { // in case client finished, remove it from the list // this list can be accessed from any thread, so lock lock (socketList) { socketList.Remove(info); } Console.WriteLine("Client finished normally."); info.socket.Close(); } } catch (Exception e) { // if problem occurs, remove socket from list too lock (socketList) { socketList.Remove(info); } Console.WriteLine("Client Disconnected."); Console.WriteLine(e); } } /// <summary> /// Test TCP client /// </summary> /// <param name="args"></param> static void Main(string[] args) { Console.WriteLine("TCP client."); Console.WriteLine(); Console.WriteLine("|--- \"exit\" to exit. ---|"); Console.WriteLine("|--- \"start {cn}\" to start {cn} number of connections.---|"); Console.WriteLine(); Console.Write("Please enter remote address and port: "); bool portReady = false; string line = Console.ReadLine(); // input management stuff. boring. while (line != "exit") { if (!portReady) { try { string[] ss = line.Split(':'); port = int.Parse(ss[1]); IPAddress add = IPAddress.Parse(ss[0]); clientEndpoint = new IPEndPoint(add, port); address = clientEndpoint.Serialize().ToString(); if (port > short.MaxValue || port < 2) { Console.WriteLine("Invalid port."); Console.Write("Please enter remote address and port: "); } else { Start(); portReady = true; } } catch { Console.WriteLine("Invalid address."); Console.Write("Please enter remote address and port: "); } } else { if (line.StartsWith("start ")) { int count = 0; try { count = int.Parse(line.Substring("start ".Length)); } catch { } Console.WriteLine("Starting " + count + " connections."); for (int i = 0; i < count; i++) { // this starts another connection Start(); } } else { try { byte[] bytes = Encoding.UTF8.GetBytes(line + "\n"); lock (socketList) { foreach (SocketInfo info in socketList) { info.socket.Send(bytes, bytes.Length, SocketFlags.None); } } } catch { Console.WriteLine("Unable to send data. Connection lost."); } } } line = Console.ReadLine(); } Console.Write("Shutting down client... "); try { lock (socketList) { for (int i = socketList.Count - 1; i >= 0; i--) { try { socketList[i].socket.Shutdown(SocketShutdown.Both); socketList[i].socket.Close(); } catch {} socketList.RemoveAt(i); } } } catch { } Console.WriteLine("Bye."); Thread.Sleep(500); } } }
项目地址:https://github.com/Nercury/csharp-tcphelpers
4. 一个简单的基于TCP协议的聊天室(支持群聊和私聊)
运行时:.NET 2.0
简介:
1. 可以把服务端和客户端的 Command 枚举和 Data 类提取到一个公共的类库中。
2. Data 中是固定头部协议,但不支持中文,要支持中文,写入用户名、字符串时需要 Convert.ToBase64String(Encoding.UTF8.GetBytes(msg)),获取的时候,则 Encoding.UTF8.GetString(Convert.FromBase64String(msg))。
服务端:
Program.cs
using System; using System.Collections.Generic; using System.Windows.Forms; namespace Server { static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new SGSserverForm()); } } }
SGSserverForm.cs
using System; using System.Collections.Generic; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Net; using System.Net.Sockets; namespace Server { //The commands for interaction between the server and the client enum Command { Login, //Log into the server Logout, //Logout of the server Message, //Send a text message to all the chat clients List, //Get a list of users in the chat room from the server Null //No command } public partial class SGSserverForm : Form { //The ClientInfo structure holds the required information about every //client connected to the server struct ClientInfo { public Socket socket; //Socket of the client public string strName; //Name by which the user logged into the chat room } //The collection of all clients logged into the room (an array of type ClientInfo) ArrayList clientList; //The main socket on which the server listens to the clients Socket serverSocket; byte[] byteData = new byte[1024]; public SGSserverForm() { clientList = new ArrayList(); InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { try { //We are using TCP sockets serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //Assign the any IP of the machine and listen on port number 1000 IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 1000); //Bind and listen on the given address serverSocket.Bind(ipEndPoint); serverSocket.Listen(4); //Accept the incoming clients serverSocket.BeginAccept(new AsyncCallback(OnAccept), null); } catch (Exception ex) { MessageBox.Show(ex.Message, "SGSserverTCP", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void OnAccept(IAsyncResult ar) { try { Socket clientSocket = serverSocket.EndAccept(ar); //Start listening for more clients serverSocket.BeginAccept(new AsyncCallback(OnAccept), null); //Once the client connects then start receiving the commands from her clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnReceive), clientSocket); } catch (Exception ex) { MessageBox.Show(ex.Message, "SGSserverTCP", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void OnReceive(IAsyncResult ar) { try { Socket clientSocket = (Socket)ar.AsyncState; clientSocket.EndReceive(ar); //Transform the array of bytes received from the user into an //intelligent form of object Data Data msgReceived = new Data(byteData); //We will send this object in response the users request Data msgToSend = new Data(); byte [] message; string clientName; //If the message is to login, logout, or simple text message //then when send to others the type of the message remains the same msgToSend.cmdCommand = msgReceived.cmdCommand; msgToSend.strName = msgReceived.strName; switch (msgReceived.cmdCommand) { case Command.Login: //When a user logs in to the server then we add her to our //list of clients ClientInfo clientInfo = new ClientInfo(); clientInfo.socket = clientSocket; clientInfo.strName = msgReceived.strName; clientList.Add(clientInfo); //Set the text of the message that we will broadcast to all users msgToSend.strMessage = "<<<" + msgReceived.strName + " has joined the room>>>"; break; case Command.Logout: //When a user wants to log out of the server then we search for her //in the list of clients and close the corresponding connection int nIndex = 0; foreach (ClientInfo client in clientList) { if (client.socket == clientSocket) { clientList.RemoveAt(nIndex); break; } ++nIndex; } clientSocket.Close(); msgToSend.strMessage = "<<<" + msgReceived.strName + " has left the room>>>"; break; case Command.Message: //Set the text of the message that we will broadcast to all users msgToSend.strMessage = msgReceived.strName + ": " + msgReceived.strMessage; msgToSend.clientName = msgReceived.clientName; break; case Command.List: //Send the names of all users in the chat room to the new user msgToSend.cmdCommand = Command.List; msgToSend.strName = null; msgToSend.strMessage = null; msgToSend.clientName = null; //Collect the names of the user in the chat room foreach (ClientInfo client in clientList) { //To keep things simple we use asterisk as the marker to separate the user names msgToSend.strMessage += client.strName + "*"; } message = msgToSend.ToByte(); //Send the name of the users in the chat room clientSocket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSend), clientSocket); break; } if (msgToSend.cmdCommand != Command.List) //List messages are not broadcasted { message = msgToSend.ToByte(); if (msgToSend.clientName != null) clientName = msgToSend.clientName; else clientName = null; foreach (ClientInfo clientInfo in clientList) { if (clientInfo.socket != clientSocket || msgToSend.cmdCommand != Command.Login) { //Send the message to all users if (clientName == null) { clientInfo.socket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSend), clientInfo.socket); } else { if(clientInfo.strName==clientName) { clientInfo.socket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSend), clientInfo.socket); } } } } //txtLog.Text += msgToSend.strMessage + "\r\n"; //MessageBox.Show(msgToSend.strMessage); } //If the user is logging out then we need not listen from her if (msgReceived.cmdCommand != Command.Logout) { //Start listening to the message send by the user clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnReceive), clientSocket); } } catch (Exception ex) { MessageBox.Show(ex.Message, "SGSserverTCP", MessageBoxButtons.OK, MessageBoxIcon.Error); } } public void OnSend(IAsyncResult ar) { try { Socket client = (Socket)ar.AsyncState; client.EndSend(ar); } catch (Exception ex) { MessageBox.Show(ex.Message, "SGSserverTCP", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } //The data structure by which the server and the client interact with //each other class Data { //Default constructor public Data() { this.cmdCommand = Command.Null; this.strMessage = null; this.strName = null; this.clientName = null; } //Converts the bytes into an object of type Data public Data(byte[] data) { //The first four bytes are for the Command this.cmdCommand = (Command)BitConverter.ToInt32(data, 0); //The next four store the length of the name int nameLen = BitConverter.ToInt32(data, 4); //The next four store the length of the message int msgLen = BitConverter.ToInt32(data, 8); int clientLen = BitConverter.ToInt32(data, 12); //This check makes sure that strName has been passed in the array of bytes if (nameLen > 0) this.strName = Encoding.UTF8.GetString(data, 16, nameLen); else this.strName = null; //This checks for a null message field if (msgLen > 0) this.strMessage = Encoding.UTF8.GetString(data, 16 + nameLen, msgLen); else this.strMessage = null; if (clientLen > 0) this.clientName = Encoding.UTF8.GetString(data, 16 + nameLen + msgLen, clientLen); else this.clientName = null; } //Converts the Data structure into an array of bytes public byte[] ToByte() { List<byte> result = new List<byte>(); //First four are for the Command result.AddRange(BitConverter.GetBytes((int)cmdCommand)); //Add the length of the name if (strName != null) result.AddRange(BitConverter.GetBytes(strName.Length)); else result.AddRange(BitConverter.GetBytes(0)); //Length of the message if (strMessage != null) result.AddRange(BitConverter.GetBytes(strMessage.Length)); else result.AddRange(BitConverter.GetBytes(0)); //Length of the clientName if (clientName != null) result.AddRange(BitConverter.GetBytes(clientName.Length)); else result.AddRange(BitConverter.GetBytes(0)); //Add the name if (strName != null) result.AddRange(Encoding.UTF8.GetBytes(strName)); //And, lastly we add the message text to our array of bytes if (strMessage != null) result.AddRange(Encoding.UTF8.GetBytes(strMessage)); if (clientName != null) result.AddRange(Encoding.UTF8.GetBytes(clientName)); return result.ToArray(); } public string strName; //Name by which the client logs into the room public string strMessage; //Message text public string clientName; public Command cmdCommand; //Command type (login, logout, send message, etcetera) } }
客户端:
下载地址:点击下载
项目地址:
https://github.com/iukash/TcpServerChat
https://github.com/iukash/TcpClientChat
5.
aaa
谢谢浏览!
作者:音乐让我说(音乐让我说 - 博客园)
出处:http://music.cnblogs.com/
文章版权归本人所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
浙公网安备 33010602011771号