1、网络聊天工具Scket编程心得网络聊天工具Scket编程心得 作者: 日期: 网络聊天工具Socket编程心得首先要了解TCP协议通信的流程:1。服务器端首先创建服务器套接字2。服务器套接字监听一个端口,等待客户端的请求3。客户端创建一个客户端套接字4。客户端向服务器发送请求5。服务器确认与客户端的连接6。客户端和服务器利用建立的连接进行通信7。通信完毕后,客户端和服务器关闭各自的连接Socket编程基础:一。利用Socket建立服务器程序1。创建一个服务器套接字,用IP地址和端口初始化服务器IPAddress ipAddress = IPAddress.Parse(127.0.0.1);Tc
2、pListener listener = new TcpListener(ipAddress, 1234);2。监听服务器端口listener.Start();3。确认与客户端的连接 Socket socket = listener.AcceptSocket();4。取得客户端传送过来的信息 /将传送过来的信息存入字节数组中byte buffer = new byte1024;socket.Receive(buffer);5。处理客户端的请求并回应客户端 string message = hello;byte outbytes = System.Text.Encoding.ASCII.GetB
3、ytes(message.ToCharArray();socket.Send(outbytes, message.Length, 0);6。断开客户端的连接,释放客户端连接 socket.Close();7。关闭服务器,释放服务器连接 listener.Close();二。利用Socket建立客户端程序1。创建客户端套接字 TcpClient tcpClient = new TcpClient();2。连接服务器 tcpClient.Connect(IPAddress.Parse(127.0.0.1), 1234);3。得到与服务器通信的流通道 NetworkStream stream = t
4、cpClient.GetStream();4。向服务器发送数据 string cmd = ;byte outbytes = System.Text.Encoding.ASCII.GetBytes(cmd.ToCharArray();stream.Write(outbytes, 0, outbytes.Length);5。接收从服务器发回的数据 byte buffer = new byte1024;int len = stream.Read(buffer, 0, buffer.Length);string msg = System.Text.Encoding.ASCII.GetString(bu
5、ffer, 0, len);6。断开连接 tcpClient.Close();服务器端窗体ChatServer.cs:using System;using System.Drawing;using System.Collections;using System.ComponentModel;using System.Windows.Forms;using System.Data;using System.Net;using System.Net.Sockets;using System.Threading;namespace ChatServer / / Form1 的摘要说明。 / publ
6、ic class ChatServerForm : System.Windows.Forms.Form / / 必需的设计器变量。 / private System.ComponentModel.Container components = null; / The port static int port = 1234; private TcpListener listener; private Socket tmpSocket; / The maximal clients the server can hold static int MaxNum = 100; private System.
7、Windows.Forms.Label label1; private System.Windows.Forms.Label label2; private System.Windows.Forms.TextBox txtHost; private System.Windows.Forms.TextBox txtPort; private System.Windows.Forms.Button btnStart; private System.Windows.Forms.Button btnExit; private System.Windows.Forms.Label label3; pri
8、vate System.Windows.Forms.ComboBox cmbCurUserList; private System.Windows.Forms.ListBox lstInfo; / The array clients is to save the online clients static ArrayList clients = new ArrayList(); public ChatServerForm() / / Windows 窗体设计器支持所必需的 / InitializeComponent(); / / TODO: 在 InitializeComponent 调用后添
9、加任何构造函数代码 / / / 清理所有正在使用的资源。 / protected override void Dispose( bool disposing ) if( disposing ) if (components != null) components.Dispose(); base.Dispose( disposing ); #region Windows 窗体设计器生成的代码 / / 设计器支持所需的方法 - 不要使用代码编辑器修改 / 此方法的内容。 / private void InitializeComponent() this.label1 = new System.Wi
10、ndows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); this.txtHost = new System.Windows.Forms.TextBox(); this.txtPort = new System.Windows.Forms.TextBox(); this.btnStart = new System.Windows.Forms.Button(); this.btnExit = new System.Windows.Forms.Button(); this.label3 = new System.Win
11、dows.Forms.Label(); this.cmbCurUserList = new System.Windows.Forms.ComboBox(); this.lstInfo = new System.Windows.Forms.ListBox(); this.SuspendLayout(); / / label1 / this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(32, 32); this.label1.Name = label1; this.label1.Size = new
12、 System.Drawing.Size(54, 17); this.label1.TabIndex = 0; this.label1.Text = 主机号:; / / label2 / this.label2.AutoSize = true; this.label2.Location = new System.Drawing.Point(32, 72); this.label2.Name = label2; this.label2.Size = new System.Drawing.Size(54, 17); this.label2.TabIndex = 1; this.label2.Tex
13、t = 端口号:; / / txtHost / this.txtHost.Location = new System.Drawing.Point(96, 24); this.txtHost.Name = txtHost; this.txtHost.Size = new System.Drawing.Size(128, 21); this.txtHost.TabIndex = 2; this.txtHost.Text = ; / / txtPort / this.txtPort.Location = new System.Drawing.Point(96, 64); this.txtPort.N
14、ame = txtPort; this.txtPort.Size = new System.Drawing.Size(128, 21); this.txtPort.TabIndex = 3; this.txtPort.Text = ; / / btnStart / this.btnStart.Location = new System.Drawing.Point(256, 24); this.btnStart.Name = btnStart; this.btnStart.TabIndex = 4; this.btnStart.Text = 启动; this.btnStart.Click +=
15、new System.EventHandler(this.btnStart_Click); / / btnExit / this.btnExit.Location = new System.Drawing.Point(256, 64); this.btnExit.Name = btnExit; this.btnExit.TabIndex = 5; this.btnExit.Text = 退出; this.btnExit.Click += new System.EventHandler(this.btnExit_Click); / / label3 / this.label3.AutoSize
16、= true; this.label3.Location = new System.Drawing.Point(24, 112); this.label3.Name = label3; this.label3.Size = new System.Drawing.Size(91, 17); this.label3.TabIndex = 6; this.label3.Text = 当前在线用户:; / / cmbCurUserList / this.cmbCurUserList.Location = new System.Drawing.Point(120, 112); this.cmbCurUs
17、erList.Name = cmbCurUserList; this.cmbCurUserList.Size = new System.Drawing.Size(136, 20); this.cmbCurUserList.TabIndex = 7; / / lstInfo / this.lstInfo.ItemHeight = 12; this.lstInfo.Location = new System.Drawing.Point(0, 144); this.lstInfo.Name = lstInfo; this.lstInfo.Size = new System.Drawing.Size(
18、344, 160); this.lstInfo.TabIndex = 8; / / ChatServerForm / this.AutoScaleBaseSize = new System.Drawing.Size(6, 14); this.ClientSize = new System.Drawing.Size(344, 301); this.Controls.Add(this.lstInfo); this.Controls.Add(this.cmbCurUserList); this.Controls.Add(this.label3); this.Controls.Add(this.btn
19、Exit); this.Controls.Add(this.btnStart); this.Controls.Add(this.txtPort); this.Controls.Add(this.txtHost); this.Controls.Add(this.label2); this.Controls.Add(this.label1); this.Name = ChatServerForm; this.Text = Form1; this.Load += new System.EventHandler(this.Form1_Load); this.ResumeLayout(false); #
20、endregion / / 应用程序的主入口点。 / STAThread static void Main() Application.Run(new ChatServerForm(); private void Form1_Load(object sender, System.EventArgs e) this.txtPort.ReadOnly = true; this.txtPort.Text = port.ToString(); this.txtHost.Text = 127.0.0.1; private void btnStart_Click(object sender, System
21、.EventArgs e) try IPAddress ip = IPAddress.Parse(this.txtHost.Text); listener = new TcpListener(ip, port); /创建服务器套字 listener.Start(); /开始监听服务器端口 lstInfo.Items.Add(服务器已经启动,正在监听 + txtHost.Text + : + txtPort.Text); /启动一个新的线程,执行方法StartListen,以便在一个独立的进程中执行确认于客户端连接的操作. Thread thread = new Thread(new Threa
22、dStart(this.StartListen); thread.Start(); btnStart.Enabled = false; catch(Exception ex) lstInfo.Items.Add(ex.Message); private void StartListen() while(true) try /当接受到一个客户端请求时,确认与客户端的连接 Socket socket = listener.AcceptSocket(); /用tmpSocket保存发出请求的客户端实例 tmpSocket = socket; if (clients.Count = MaxNum) t
23、mpSocket.Close(); else /启动一个新的线程,执行方法this.ServiceClient,处理用户相应的要求 Thread clientService = new Thread(new ThreadStart(this.ServiceClient); clientService.Start(); catch(Exception ex) lstInfo.Items.Add(ex.Message); private void ServiceClient() /定义一个数组,用于接收从客户端发送过来的数据,每次所能接收的数据包的最大长度为1024字节 byte buffer =
24、 new byte1024; Socket clientSocket = tmpSocket; bool keepConnect = true; /用循环不断地与客户端进行交互,直到客户端发出Exit命令,将keepConnect设置为false /退出循环,关闭连接,中止当前线程 while(keepConnect) /接收数据并存入buffer数组中 clientSocket.Receive(buffer); /将字符数组转化为字符串 string clientCommand = System.Text.Encoding.ASCII.GetString(buffer); string to
25、kens = clientCommand.Split(|); /tokens0中保存了命令标识符(CONN或CHAT或PRIV或EXIT) if (tokens0 = CONN) / CONN|用户名| Client _client = new Client(tokens1, clientSocket); clients.Add(_client); lstInfo.Items.Add(tokens1 + has joined); /将刚连接的用户名加入到当前在线用户列表中 this.cmbCurUserList.Items.Add(tokens1); /对每一个在线用户发送JOIN和LIST信
26、息命令,以此来更新客户端的在线用户列表 for(int i=0; iclients.Count; i+) Client client = (Client)clientsi; /向客户端发送JOIN命令,以此来提示有新的客户进入聊天室 SendToClient(client, JOIN| + tokens1 + |); Thread.Sleep(100); string msgUsers = LIST| + GetUserList(); /向客户端发送LIST命令,以此来更新客户端的当前在线用户列表 SendToClient(client, msgUsers); if (tokens0 = CH
27、AT) / CHAT|用户名:内容| /向所有当前在线用户转发此信息 for (int i=0; iclients.Count; i+) Client client = (Client)clientsi; /将发送者的用户名:发送内容转发给用户 SendToClient(client, tokens1); if (tokens0 = PRIV) / PRIV|发送者用户名|接受者用户名|发送内容 string sender = tokens1; string receiver = tokens2; string content = tokens3; string message = sende
28、r + send to + receiver + : + content; /仅把信息转发给发送者和接收者 for (int i=0; iclients.Count; i+) Client client = (Client)clientsi; if (client.Name = tokens2) this.SendToClient(client, message); if (client.Name = tokens1) this.SendToClient(client, message); if (tokens0 = EXIT) / EXIT|用户名 for (int i=0; iclients.Count; i+) Client client = (Client)clientsi; string message = tokens1 + has gone!; this.SendToClient(client, message); if (client.Name = tokens1) /将该用户从对应的Client对象从clients数组中删除 clients.RemoveAt(i); /将该用户名从当前在线用户列表中删除 this.cmbCurUserList.Items.Remove(client.Name); /向客户端发送QUIT命令,以此来关闭客户端程序 message