服务器端:
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
{
/// <summary>
/// Form1 的摘要说明。
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.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;
private System.Windows.Forms.ComboBox curUserList;
private System.Windows.Forms.ListBox lstInfo;
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;
//该服务器默认的监听端口号
static int port=1234;
private TcpListener listener;
private Socket tmpSocket;
//最多客户端连接数
static int MaxNum=100;
//clients数组保持当前在线的client对象
static ArrayList clients=new ArrayList();
public Form1()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.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.Windows.Forms.Label();
this.curUserList = new System.Windows.Forms.ComboBox();
this.lstInfo = new System.Windows.Forms.ListBox();
this.SuspendLayout();
//
// label1
//
this.label1.Location = new System.Drawing.Point(0, 16);
this.label1.Name = "label1";
this.label1.TabIndex = 0;
this.label1.Text = "主机号:";
this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// label2
//
this.label2.Location = new System.Drawing.Point(0, 56);
this.label2.Name = "label2";
this.label2.TabIndex = 1;
this.label2.Text = "端口号:";
this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// txtHost
//
this.txtHost.Location = new System.Drawing.Point(104, 16);
this.txtHost.Name = "txtHost";
this.txtHost.Size = new System.Drawing.Size(128, 21);
this.txtHost.TabIndex = 2;
this.txtHost.Text = "192.168.0.163";
//
// txtPort
//
this.txtPort.Location = new System.Drawing.Point(104, 56);
this.txtPort.Name = "txtPort";
this.txtPort.ReadOnly = true;
this.txtPort.Size = new System.Drawing.Size(128, 21);
this.txtPort.TabIndex = 3;
this.txtPort.Text = "";
//
// btnStart
//
this.btnStart.Location = new System.Drawing.Point(264, 16);
this.btnStart.Name = "btnStart";
this.btnStart.TabIndex = 4;
this.btnStart.Text = "启动";
this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
//
// btnExit
//
this.btnExit.Location = new System.Drawing.Point(264, 56);
this.btnExit.Name = "btnExit";
this.btnExit.TabIndex = 5;
this.btnExit.Text = "退出";
this.btnExit.Click += new System.EventHandler(this.btnExit_Click);
//
// label3
//
this.label3.Location = new System.Drawing.Point(24, 136);
this.label3.Name = "label3";
this.label3.TabIndex = 6;
this.label3.Text = "当前在线用户:";
this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// curUserList
//
this.curUserList.Location = new System.Drawing.Point(160, 136);
this.curUserList.Name = "curUserList";
this.curUserList.Size = new System.Drawing.Size(121, 20);
this.curUserList.TabIndex = 7;
//
// lstInfo
//
this.lstInfo.ItemHeight = 12;
this.lstInfo.Location = new System.Drawing.Point(24, 184);
this.lstInfo.Name = "lstInfo";
this.lstInfo.Size = new System.Drawing.Size(408, 148);
this.lstInfo.TabIndex = 8;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(464, 381);
this.Controls.Add(this.lstInfo);
this.Controls.Add(this.curUserList);
this.Controls.Add(this.label3);
this.Controls.Add(this.btnExit);
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 = "Form1";
this.Text = "ChatServer";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void Form1_Load(object sender, System.EventArgs e)
{
}
/// <summary>
/// 启动
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStart_Click(object sender, System.EventArgs e)
{
txtPort.Text=port.ToString();
string myip=txtHost.Text;
try
{
IPAddress ipAdd=IPAddress.Parse(myip);
//创建服务器套接字
listener=new TcpListener(ipAdd,port);
//开始监听服务器端口
listener.Start();
lstInfo.Items.Add("服务器已经启动,正在监听"+txtHost.Text+":"+txtPort.Text);
//启动一个线程,执行this.StartListen,在一个独立的进程中执行确认与客户连接的操作
Thread thread= new Thread(new ThreadStart(this.StartListen));
thread.Start();
btnStart.Enabled=false;
}
catch(Exception ex)
{
lstInfo.Items.Add(ex.Message.ToString());
}
}
/// <summary>
/// StartListener()方法是在新的线程中进行的,它主要用于当接手到一个客户端请求的时候,
/// 确认与客户端的连接,并却立刻启动一个新的线程来处理和该客户端的信息交互
/// </summary>
private void StartListen()
{
while(true)
{
try
{
//当接收到一个客户端请求时,确认与客户端的连接
Socket socket = listener.AcceptSocket();
//用tmpSocket保存发出请求的客户端实例
tmpSocket=socket;
if(clients.Count>=MaxNum)
{
tmpSocket.Close();
}
else
{
//启动一个新的线程,执行方法this.ServiceClient,处理用户相应的请求
Thread clientService=new Thread(new ThreadStart(this.ServiceClient));
clientService.Start();
}
}
catch(Exception ex)
{
lstInfo.Items.Add(ex.Message.ToString());
}
}
}
/// <summary>
/// 用于和客户端进行通信
/// </summary>
private void ServiceClient()
{
//定义一个byte数组,用于接收从客户端发送过来的数据,每次所能结合艘的数据包的最大长度是1024个字节
byte[] buff=new byte[1024];
Socket clientSocket = tmpSocket;
bool keepConnect=true;
//用循环不断的与客户端进行交互,知道客户端发出“exit”命令,
while(keepConnect)
{
clientSocket.Receive(buff);
//将字符数组转换成字符串
string clientCommand=System.Text.Encoding.ASCII.GetString(buff);
string[] tokens=clientCommand.Split(new char[]{'|'});
//tokens[0]中保存的自己定义的命令
if(tokens[0]=="CONN")
{
Client _client=new Client(tokens[1],clientSocket);
clients.Add(_client);
lstInfo.Items.Add(tokens[1]+" "+"进入");
//把进入的人加进在线列表
curUserList.Items.Add(tokens[1]);
//更新客户端的在线用户列表
for(int i=0;i<clients.Count;i++)
{
Client client=(Client)clients[i];
//向客户端发送join命令,提示有新的用户进入
SendToClient(client,"JOIN|"+tokens[1]+"|");
Thread.Sleep(100);
string msgUsers="LIST|"+GetUserList();
SendToClient(client,msgUsers);
}
}
if(tokens[0]=="CHAT")
{
//向所有当前在线用户发送消息
for(int i=0;i<clients.Count;i++)
{
Client client=(Client)clients[i];
SendToClient(client,tokens[1]);
}
}
if(tokens[0]=="PRIV")
{
//悄悄话
string sender=tokens[1];
string receiver=tokens[2];
string content=tokens[3];
string message=sender+" send to "+receiver+": "+content;
for(int i=0;i<clients.Count;i++)
{
Client client=(Client)clients[i];
if(client.Name.CompareTo(tokens[2])==0)
SendToClient(client,message);
if(client.Name.CompareTo(tokens[1])==0)
SendToClient(client,message);
}
}
if(tokens[0]=="EXIT")
{
for(int i=0;i<clients.Count;i++)
{
Client client=(Client)clients[i];
string message=tokens[1]+"下线";
SendToClient(client,message);
if(client.Name.CompareTo(tokens[1])==0)
{
clients.RemoveAt(i);
curUserList.Items.Remove(client.Name);
//向客户端发送QUIT命令,关闭客户端程序
message="QUIT|";
SendToClient(client,message);
}
}
//向所有的客户端发送list命令,更新在线用户
for(int i=0;i<clients.Count;i++)
{
Client client=(Client)clients[i];
string message="LIST|"+GetUserList();
SendToClient(client,message);
}
lstInfo.Items.Add(tokens[1]+"退出");
clientSocket.Close();
keepConnect=false;
}
}
}
/// <summary>
/// 向客户端发送命令请求
/// </summary>
/// <param name="client"></param>
/// <param name="msg"></param>
private void SendToClient(Client client,string msg)
{
System.Byte[]message=System.Text.Encoding.ASCII.GetBytes(msg.ToCharArray());
client.clientSocket.Send(message,message.Length,0);
}
/// <summary>
/// 获取当前用户列表
/// </summary>
/// <returns></returns>
private string GetUserList()
{
string Rtn="";
for(int i=0;i<clients.Count;i++)
{
Client client=(Client)clients[i];
Rtn=Rtn+client.Name+"|";
}
return Rtn;
}
/// <summary>
/// 退出
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnExit_Click(object sender, System.EventArgs e)
{
Application.Exit();
}
}
public class Client
{
string name;
Socket clSocket;
public Client(string _name,Socket _socket)
{
name=_name;
clSocket=_socket;
}
public string Name
{
get
{
return name;
}
set
{
name=value;
}
}
public Socket clientSocket
{
get
{
return clSocket;
}
set
{
clSocket=value;
}
}
}
}
客户端:
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 ChatClient
{
/// <summary>
/// Form1 的摘要说明。
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.TextBox txtSendContent;
private System.Windows.Forms.Button btnSend;
private System.Windows.Forms.ListBox lstContent;
private System.Windows.Forms.ListBox lstUsers;
private System.Windows.Forms.CheckBox priCheckBox;
private System.Windows.Forms.TextBox txtAlias;
private System.Windows.Forms.Label status;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Label labAlias;
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;
//与服务器连接
private TcpClient tcpclient;
//与服务器数据交互的通道流
private NetworkStream Strm;
//用户名
private string UserAlias;
//是否为悄悄话
private bool privatemode=false;
//
public TcpClient tcpClient;
//
public string Alias="";
public Form1()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.txtAlias = new System.Windows.Forms.TextBox();
this.lstContent = new System.Windows.Forms.ListBox();
this.lstUsers = new System.Windows.Forms.ListBox();
this.priCheckBox = new System.Windows.Forms.CheckBox();
this.txtSendContent = new System.Windows.Forms.TextBox();
this.btnSend = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.status = new System.Windows.Forms.Label();
this.button1 = new System.Windows.Forms.Button();
this.labAlias = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.Location = new System.Drawing.Point(0, 8);
this.label1.Name = "label1";
this.label1.TabIndex = 0;
this.label1.Text = "姓名:";
this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// txtAlias
//
this.txtAlias.Location = new System.Drawing.Point(104, 8);
this.txtAlias.Name = "txtAlias";
this.txtAlias.TabIndex = 1;
this.txtAlias.Text = "";
//
// lstContent
//
this.lstContent.ItemHeight = 12;
this.lstContent.Location = new System.Drawing.Point(8, 72);
this.lstContent.Name = "lstContent";
this.lstContent.Size = new System.Drawing.Size(272, 244);
this.lstContent.TabIndex = 2;
//
// lstUsers
//
this.lstUsers.ItemHeight = 12;
this.lstUsers.Location = new System.Drawing.Point(8, 368);
this.lstUsers.Name = "lstUsers";
this.lstUsers.Size = new System.Drawing.Size(72, 88);
this.lstUsers.TabIndex = 3;
//
// priCheckBox
//
this.priCheckBox.Location = new System.Drawing.Point(96, 368);
this.priCheckBox.Name = "priCheckBox";
this.priCheckBox.TabIndex = 4;
this.priCheckBox.Text = "悄悄话";
this.priCheckBox.CheckedChanged += new System.EventHandler(this.priCheckBox_CheckedChanged);
//
// txtSendContent
//
this.txtSendContent.Location = new System.Drawing.Point(96, 400);
this.txtSendContent.Name = "txtSendContent";
this.txtSendContent.Size = new System.Drawing.Size(184, 21);
this.txtSendContent.TabIndex = 5;
this.txtSendContent.Text = "";
//
// btnSend
//
this.btnSend.Enabled = false;
this.btnSend.Location = new System.Drawing.Point(104, 432);
this.btnSend.Name = "btnSend";
this.btnSend.TabIndex = 6;
this.btnSend.Text = "发送";
this.btnSend.Click += new System.EventHandler(this.btnSend_Click);
//
// button2
//
this.button2.Location = new System.Drawing.Point(200, 432);
this.button2.Name = "button2";
this.button2.TabIndex = 7;
this.button2.Text = "离开";
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// status
//
this.status.Location = new System.Drawing.Point(8, 328);
this.status.Name = "status";
this.status.TabIndex = 8;
this.status.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// button1
//
this.button1.Location = new System.Drawing.Point(216, 8);
this.button1.Name = "button1";
this.button1.TabIndex = 9;
this.button1.Text = "连接";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// labAlias
//
this.labAlias.Location = new System.Drawing.Point(96, 40);
this.labAlias.Name = "labAlias";
this.labAlias.TabIndex = 10;
this.labAlias.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(296, 501);
this.Controls.Add(this.labAlias);
this.Controls.Add(this.button1);
this.Controls.Add(this.status);
this.Controls.Add(this.button2);
this.Controls.Add(this.btnSend);
this.Controls.Add(this.txtSendContent);
this.Controls.Add(this.priCheckBox);
this.Controls.Add(this.lstUsers);
this.Controls.Add(this.lstContent);
this.Controls.Add(this.txtAlias);
this.Controls.Add(this.label1);
this.Name = "Form1";
this.Text = "Login";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
/// <summary>
/// 加载窗体
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Load(object sender, System.EventArgs e)
{
/*
try
{
Login dlgLogin=new Login();
//显示Login对话框
DialogResult result=dlgLogin.ShowDialog();
if(result==DialogResult.OK)
{
UserAlias=dlgLogin.Alias;
txtAlias.Text=UserAlias;
//当Login窗口登陆成功后tcpClient中保存着与服务器的连接
tcpclient=dlgLogin.tcpClient;
Strm=tcpclient.GetStream();
dlgLogin.Close();
}
else
{
//用户在登陆窗口中点了取消
lstUsers.Enabled=false;
txtSendContent.Enabled=false;
btnSend.Enabled=false;
dlgLogin.Close();
}
//启动一个新的线程,执行方法this.ServerResponse(),响音服务器的消息
Thread thread=new Thread(new ThreadStart(this.ServerResponse));
thread.Start();
//向服务器发送"CONN"请求命令
string cmd="CONN|"+UserAlias+"|";
Byte[] outbytes=System.Text.Encoding.ASCII.GetBytes(cmd.ToCharArray());
Strm.Write(outbytes,0,outbytes.Length);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
*/
}
/// <summary>
/// 响音服务器的消息
/// </summary>
private void ServerResponse()
{
byte[] buff=new byte[1024];
string msg;
int len;
try
{
if(!Strm.CanRead)
return;
//用循环不断的与服务器交互
while(true)
{
len=Strm.Read(buff,0,buff.Length);
msg=System.Text.Encoding.ASCII.GetString(buff,0,len);
msg.Trim();
string[] tokens=msg.Split(new char[]{'|'});
if(tokens[0]=="LIST")
{
status.Text="在线";
labAlias.Text=UserAlias;
lstUsers.Items.Clear();
for(int i=1;i<tokens.Length-1;i++)
lstUsers.Items.Add(tokens[i].Trim());
}
if(tokens[0]=="JOIN")
{
lstContent.Items.Add(tokens[1]+" 进入");
}
if(tokens[0]=="QUIT")
break;
if(tokens[0]!="JOIN"&&tokens[0]!="LIST"&&tokens[0]!="QUIT")
{
lstContent.Items.Add(msg);
}
}
tcpclient.Close();
this.Close();
}
catch
{
lstContent.Items.Add("网络发生错误");
}
}
/// <summary>
/// 是否为悄悄话
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void priCheckBox_CheckedChanged(object sender, System.EventArgs e)
{
if(priCheckBox.Checked)
privatemode=true;
else
privatemode=false;
}
/// <summary>
/// 发送
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSend_Click(object sender, System.EventArgs e)
{
try
{
if(!privatemode)
{
string message="CHAT|"+UserAlias+":"+txtSendContent.Text+"|";
txtSendContent.Text="";
txtSendContent.Focus();
Byte[] outbytes=System.Text.Encoding.ASCII.GetBytes(message.ToCharArray());
Strm.Write(outbytes,0,outbytes.Length);
}
else
{
if(lstUsers.SelectedIndex==-1)
{
MessageBox.Show("请选择一个用户");
return;
}
string receiver=lstUsers.SelectedItem.ToString();
string message="PRIV|"+UserAlias+"|"+receiver+"|"+txtSendContent.Text+"|";
txtSendContent.Text="";
txtSendContent.Focus();
Byte[] outbytes=System.Text.Encoding.ASCII.GetBytes(message.ToCharArray());
Strm.Write(outbytes,0,outbytes.Length);
}
}
catch
{
lstContent.Items.Add("网络发生错误");
}
}
/// <summary>
/// 离开
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, System.EventArgs e)
{
string message="EXIT|"+UserAlias+"|";
Byte[] outbytes=System.Text.Encoding.ASCII.GetBytes(message.ToCharArray());
Strm.Write(outbytes,0,outbytes.Length);
}
/// <summary>
/// 连接
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, System.EventArgs e)
{
try
{
tcpClient=new TcpClient();
//向指定的ip地址的服务器发送连接请求
tcpClient.Connect(IPAddress.Parse("192.168.0.163"),Int32.Parse("1234"));
UserAlias=txtAlias.Text;
Strm=tcpClient.GetStream();
//启动一个新的线程,执行方法this.ServerResponse(),响音服务器的消息
Thread thread=new Thread(new ThreadStart(this.ServerResponse));
thread.Start();
//向服务器发送"CONN"请求命令
string cmd="CONN|"+UserAlias+"|";
Byte[] outbytes=System.Text.Encoding.ASCII.GetBytes(cmd.ToCharArray());
Strm.Write(outbytes,0,outbytes.Length);
btnSend.Enabled=true;
}
catch(Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
}
}