注:只能在服务器和客户端不再同一台PC上实现通信,同一台PC无法利用封装的类实现客户端与服务器通信!!!
由于还是初学C#,目前还不知道什么原因!!!记录下...
网络聊天系统:
服务器相关:
首先声明一个用户相关的类:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace TcpService_ListenerAndClient
{
public class TcpServiceBSD
{
private BinaryReader _br;
private BinaryWriter _bw;
private TcpClient _client;
private string _userName;
public BinaryReader Br
{
get
{
return _br;
}
set
{
_br = value;
}
}
public BinaryWriter Bw
{
get
{
return _bw;
}
set
{
_bw = value;
}
}
public TcpClient Client
{
get
{
return _client;
}
set
{
_client = value;
}
}
public string UserName
{
get
{
return _userName;
}
set
{
_userName = value;
}
}
public TcpServiceBSD(TcpClient client/*,string _localIp,int _localPort*/)
{
this.Client = client;
NetworkStream networkStream = client.GetStream();
Br = new BinaryReader(networkStream);
Bw = new BinaryWriter(networkStream);
//this.LocalIpAddress = IPAddress.Parse(_localIp);
//this.LocalPort = _localPort;
}
public void Close()
{
Br.Close();
Bw.Close();
this.Client.Close();
}
}
}
UI界面的:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TcpService_ListenerAndClient
{
public partial class TcpService : Form
{
//public Dictionary dicTcpClient = new Dictionary();
//声明一个存放用户的集合
private List userList = new List();
//声明本地IP地址
IPAddress localAddress;
//声明本地端口号
private const int localPort = 5000;
//声明用来监听的对象
private TcpListener myListener;
//指示是否正常退出
bool isNormalExit = false;
//public delegate void AddMsgToText(string text);
//声明一个跨线程的委托实现对ListBox的操作
public delegate void AddMsgToListBox(string str);
//void AddMsgToTxtLog(string str)
//{
// if(txtLog.InvokeRequired)
// {
// AddMsgToText addMsgToText = new AddMsgToText(AddMsgToTxtLog);
// txtLog.Invoke(addMsgToText, DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd hh:mm:ss.fff") + " "+str);
// }
// else
// {
// txtLog.AppendText(DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd hh:mm:ss.fff") + " " + str);
// }
//}
//声明一个跨线程的委托实现对ListBox的操作
void AddMsgToLtbUsers(string str)
{
if(ltbUsers.InvokeRequired)
{
AddMsgToListBox addMsgToListBox= new AddMsgToListBox(AddMsgToLtbUsers);
ltbUsers.Invoke(addMsgToListBox, str);
}
else
{
ltbUsers.Items.Add(str);
ltbUsers.SelectedIndex = ltbUsers.Items.Count - 1;
ltbUsers.ClearSelected();
}
}
public TcpService()
{
InitializeComponent();
//获取本地IP地址,以及设置界面相关的属性
ltbUsers.HorizontalScrollbar = true;
IPAddress[] addrIp = Dns.GetHostAddresses(Dns.GetHostName());
localAddress = addrIp[addrIp.Length -1];
txtLocalIp.Text = localAddress.ToString();
txtLocalListenPort.Text = localPort.ToString();
txtSendMsg.Enabled = false;
btnSendMsg.Enabled = false;
btnStopListen.Enabled = false;
txtLocalIp.Enabled = false;
txtLocalListenPort.Enabled = false;
}
private void TcpService_Load(object sender, EventArgs e)
{
}
//开始监听按钮
private void btnStartListen_Click(object sender, EventArgs e)
{
//实例化监听对象
myListener = new TcpListener(localAddress, localPort);
//开启监听
myListener.Start();
//AddMsgToTxtLog("开始在:" + localAddress.ToString() + localPort.ToString() + "监听客户连接");
AddMsgToLtbUsers(string.Format("开始在{0}:{1}监听客户连接", localAddress, localPort));
//开起一个用来监听的后台线程
Thread myThread = new Thread(ListenClientConnect);
myThread.Start();
btnStartListen.Enabled = false;
btnStopListen.Enabled = true;
}
//监听后台线程执行的方法
private void ListenClientConnect()
{
//声明一个用来存储连接对象的TcpClient对象
TcpClient newClient = null;
while(true)
{
try
{
//接收该对象
newClient = myListener.AcceptTcpClient();
}
catch
{
break;
}
//将该用户的相关信息使用封装的类存储
TcpServiceBSD tcpServerBSD = new TcpServiceBSD(newClient);
//开启一个不停接收的线程
Thread threadReceive = new Thread(ReceiveData);
threadReceive.Start(tcpServerBSD);
//将接收的用户存储到集合中并显示在ListBox控件中
userList.Add(tcpServerBSD);
//AddMsgToTxtLog(newClient.Client.RemoteEndPoint.ToString() + "进入.");
//AddMsgToTxtLog("当前连接的用户数:" + userList.Count.ToString() + ".");
AddMsgToLtbUsers(string.Format("[{0}]进入", newClient.Client.RemoteEndPoint));
AddMsgToLtbUsers(string.Format("当前连接用户数:{0}", userList.Count));
}
}
//接收监听端口发送的数据
private void ReceiveData(object userState)
{
TcpServiceBSD user = userState as TcpServiceBSD;
TcpClient client = user.Client;
while(isNormalExit ==false)
{
string receiveString = null;
try
{
//用BinaryReader的方法读取网络流中的数据
receiveString = user.Br.ReadString();
}
catch
{
if(isNormalExit ==false)
{
//AddMsgToTxtLog("已与" + client.Client.RemoteEndPoint.ToString() + "失去联系,已终止接收该用户信息");
AddMsgToLtbUsers(string.Format("与{0}失去联系,,已终止接收该用户信息", client.Client.RemoteEndPoint));
RemoveUser(user);
}
break;
}
//AddMsgToTxtLog("来自:" + user.Client.Client.RemoteEndPoint.ToString() + ":" + receiveString);
AddMsgToLtbUsers(string.Format("来自:[{0}]:{1}", user.Client.Client.RemoteEndPoint, receiveString));
string[] splitString = receiveString.Split(',');
switch (splitString[0])
{
case "Login":
{
user.UserName = splitString[1];
SendToAllClient(user, receiveString);
break;
}
case "Logout":
{
SendToAllClient(user, receiveString);
RemoveUser(user);
return;
}
case "Talk":
{
string talkString = receiveString.Substring(splitString[0].Length + splitString[1].Length + 2);
//AddMsgToTxtLog(user.UserName + "对" + splitString[1] + "说:" + talkString);
AddMsgToLtbUsers(string.Format("[{0}]对[{1}]说:{2}", user.UserName, splitString[1], talkString));
SendToClient(user, "talk," + user.UserName + "," + talkString);
foreach(TcpServiceBSD target in userList)
{
if(target.UserName ==splitString[1] && user.UserName != splitString[1])
{
SendToClient(target, "talk," + user.UserName + "," + talkString);
break;
}
}
break;
}
default:
{
//AddMsgToTxtLog("什么意思啊:" + receiveString);
AddMsgToLtbUsers(string.Format("什么意思啊:{0}", receiveString));
break;
}
}
}
}
private void SendToClient(TcpServiceBSD user,string message)
{
try
{
//利用BinaryWriter的方法向网络流中写入数据
user.Bw.Write(message);
user.Bw.Flush();
//AddMsgToTxtLog("向" + user.UserName + "发送:" + message);
AddMsgToLtbUsers(string.Format("向[{0}]发送:{1}", user.UserName, message));
}
catch
{
//AddMsgToTxtLog("向" + user.UserName + "发送信息失败");
AddMsgToLtbUsers(string.Format("向[{0}]发送信息失败!", user.UserName));
}
}
private void SendToAllClient(TcpServiceBSD user,string message)
{
string command = message.Split(',')[0].ToLower();
if(command =="login")
{
for(int i =0;i< userList.Count;i++)
{
SendToClient(userList[i], message);
if(userList[i].UserName != user.UserName)
{
SendToClient(user, "login," + userList[i].UserName);
}
}
}
else if(command == "logout")
{
for (int i = 0; i < userList.Count; i++)
{
if (userList[i].UserName != user.UserName)
{
SendToClient(userList[i], message);
}
}
}
}
private void RemoveUser(TcpServiceBSD user)
{
userList.Remove(user);
user.Close();
//AddMsgToTxtLog(string.Format("当前连接的用户数:{0}", userList.Count));
AddMsgToLtbUsers(string.Format("当前连接的用户数:{0}", userList.Count));
}
private void btnStopListen_Click(object sender, EventArgs e)
{
AddMsgToLtbUsers("开始停止服务,并依次使用户退出!");
isNormalExit = true;
for(int i=userList.Count-1;i>=0;i--)
{
RemoveUser(userList[i]);
}
myListener.Stop();
btnStartListen.Enabled = true;
btnStopListen.Enabled = false;
}
private void TcpService_FormClosing(object sender, FormClosingEventArgs e)
{
if(myListener !=null)
{
btnStopListen.PerformClick();
}
}
}
}
UI界面相关:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TcpClient_Client
{
public partial class TcpClientForm : Form
{
private bool isExit = false;
private TcpClient client;
private BinaryReader br;
private BinaryWriter bw;
public TcpClientForm()
{
InitializeComponent();
//产生一个随机的用户名
Random r = new Random((int)DateTime.Now.Ticks);
txtUserName.Text = "user" + r.Next(100, 999);
ltbCurrentOnline.HorizontalScrollbar = true;
txtServiceIp.Enabled = false;
txtServicePort.Enabled = false;
btnSatrtConnect.Enabled = false;
btnStopConnect.Enabled = false;
}
private void TcpClient_Load(object sender, EventArgs e)
{
}
private void btnLogin_Click(object sender, EventArgs e)
{
btnLogin.Enabled = false;
try
{
//本地发送端的先关地址信息及端口号
IPAddress iep = IPAddress.Parse("192.168.1.114");
IPEndPoint ip = new IPEndPoint(iep, 50000);
//连接的远程主机的地址及端口号信息
IPAddress remIp = IPAddress.Parse("192.168.1.150");
IPEndPoint remIep = new IPEndPoint(remIp, 50000);
client = new TcpClient(ip);
//client.Connect(ip);
client.Connect(remIp, 50000);
//client = new TcpClient(Dns.GetHostName(), 50000);
txtServiceIp.Text = client.Client.RemoteEndPoint.ToString();
AddTalkMessage("连接成功");
}
catch
{
AddTalkMessage("连接失败");
btnLogin.Enabled = true;
return;
}
NetworkStream networkStream = client.GetStream();
br = new BinaryReader(networkStream);
bw = new BinaryWriter(networkStream);
SendMessage("Login," + txtUserName.Text);
Thread threadReceive = new Thread(new ThreadStart(ReceiveData));
threadReceive.IsBackground = true;
threadReceive.Start();
}
private void ReceiveData()
{
string receiveString = null;
while(isExit ==false)
{
try
{
receiveString = br.ReadString();
}
catch
{
if(isExit ==false)
{
MessageBox.Show("与服务器失去联系!");
}
break;
}
string[] splitString = receiveString.Split(',');
string command = splitString[0].ToLower();
switch(command)
{
case "login":
{
AddOnline(splitString[1]);
break;
}
case "logout":
{
RemoveUserName(splitString[1]);
break;
}
case "talk":
{
AddTalkMessage(splitString[1] + ":\r\n");
AddTalkMessage(receiveString.Substring(splitString[0].Length + splitString[1].Length + 2));
break;
}
default:
{
AddTalkMessage("什么意思啊:" + receiveString);
break;
}
}
}
Application.Exit();
}
private void SendMessage(string message)
{
try
{
bw.Write(message);
bw.Flush();
}
catch
{
AddTalkMessage("发送失败!");
}
}
private void btnSendMsg_Click(object sender, EventArgs e)
{
if(ltbCurrentOnline.SelectedIndex !=-1)
{
SendMessage("Talk," + ltbCurrentOnline.SelectedItem + "," + txtSendMsg.Text + "\r\n");
txtSendMsg.Clear();
}
else
{
MessageBox.Show("请在【当前在线用户】中选择一个对话者");
}
}
private void TcpClientForm_FormClosing(object sender, FormClosingEventArgs e)
{
if(client !=null)
{
SendMessage("Logout," + txtUserName.Text);
isExit = true;
br.Close();
bw.Close();
client.Close();
}
}
private delegate void MessageDelegate(string message);
private void AddTalkMessage(string message)
{
if(txtLog.InvokeRequired)
{
MessageDelegate d = new MessageDelegate(AddTalkMessage);
txtLog.Invoke(d,new object[] { message });
}
else
{
txtLog.AppendText(message + Environment.NewLine);
txtLog.ScrollToCaret();
}
}
private delegate void AddOnlineDelegate(string message);
private void AddOnline(string userName)
{
if(ltbCurrentOnline.InvokeRequired)
{
AddOnlineDelegate d = new AddOnlineDelegate(AddOnline);
ltbCurrentOnline.Invoke(d, new object[] { userName });
}
else
{
ltbCurrentOnline.Items.Add(userName);
ltbCurrentOnline.SelectedIndex = ltbCurrentOnline.Items.Count - 1;
ltbCurrentOnline.ClearSelected();
}
}
private delegate void RemoveUserNameDelegate(string userName);
private void RemoveUserName(string userName)
{
if (ltbCurrentOnline.InvokeRequired)
{
RemoveUserNameDelegate d = new RemoveUserNameDelegate(RemoveUserName);
ltbCurrentOnline.Invoke(d, new object[] { userName });
}
else
{
ltbCurrentOnline.Items.Remove(userName);
ltbCurrentOnline.SelectedIndex = ltbCurrentOnline.Items.Count - 1;
ltbCurrentOnline.ClearSelected();
}
}
private void btnSatrtConnect_Click(object sender, EventArgs e)
{
try
{
IPAddress iep = IPAddress.Parse("192.168.1.150");
IPEndPoint ip = new IPEndPoint(iep, 50000);
//client = new TcpClient("192.168.1.150", 50000);
client = new TcpClient(ip);
client.Connect(ip);
txtServiceIp.Text = client.Client.RemoteEndPoint.ToString();
AddTalkMessage("连接成功");
}
catch
{
AddTalkMessage("连接失败");
btnLogin.Enabled = true;
return;
}
NetworkStream networkStream = client.GetStream();
br = new BinaryReader(networkStream);
bw = new BinaryWriter(networkStream);
SendMessage("Login," + txtUserName.Text);
Thread threadReceive = new Thread(new ThreadStart(ReceiveData));
threadReceive.IsBackground = true;
threadReceive.Start();
}
}
}