目录
有更好的想法可以交流
WCF部分
要用双工通信先配置文件在Web.config那里,怎么配置自行搜索。
关于WCF和WPF的服务引用可以看这篇文章WPF调WCF服务端
Service1.svc.cs源码
using GobangGameWcfService;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WcfService_ChatService
{
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“Service1”。
// 注意: 为了启动 WCF 测试客户端以测试此服务,请在解决方案资源管理器中选择 Service1.svc 或 Service1.svc.cs,然后开始调试。
public class Service1 : IService1
{
public Service1()
{
if (Users.userList == null)
Users.userList = new List<User>();
}
private IChatServiceCallback callback;
public void Login(string username)
{
OperationContext context = OperationContext.Current;
callback = context.GetCallbackChannel<IChatServiceCallback>();
User newUser = new User(username, callback);
newUser.userName = username;
foreach (var userone in Users.userList)
{
if(newUser.userName == userone.userName)
{
callback.ShowWrongLogin(userone.userName);
return;
}
}
Users.userList.Add(newUser);
foreach (var usertwo in Users.userList)
{
usertwo.callback.ShowLogin(username, Users.userList.Count);
//usertwo.callback.ShowUserList(Users.userList);
}
}
public void Logout(string userName)
{
User removeUser = null;
foreach (User one in Users.userList)
{
if (one.userName == userName)
{
removeUser = one;
break;
}
}
if(removeUser == null)
{
callback.ShowWrongLogout(userName);
return;
}
Users.userList.Remove(removeUser);
foreach (var user in Users.userList)
{
user.callback.ShowLogout(userName, Users.userList.Count);
user.callback.ShowUserList(Users.userList);
}
}
public void sendInfo(string info , string userName)
{
foreach (var user in Users.userList)
{
user.callback.ShowSendInfo(info, userName);
}
}
public void PrivateChat(string userName, string SelectName, string T)
{
foreach(User user in Users.userList)
{
if(user.userName == SelectName)
{
user.callback.ShowPrivateChat(userName,T);
}
}
}
public void LoginList()
{
foreach (User user in Users.userList)
{
user.callback.ShowUserList(Users.userList);
}
}
public class Users
{
public static List<User> userList;
}
}
}
IService1.cs源码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using static WcfService_ChatService.Service1;
namespace WcfService_ChatService
{
[ServiceContract(CallbackContract = typeof(IChatServiceCallback))]
//服务端
public interface IService1
{
[OperationContract(IsOneWay = true)]
void Login(string userName);
[OperationContract(IsOneWay = true)]
void sendInfo(string info,string userName);
[OperationContract(IsOneWay = true)]
void Logout(string userName);
[OperationContract(IsOneWay = true)]
void LoginList();
[OperationContract(IsOneWay = true)]
void PrivateChat(string userName , string SelectName , string Text);
}
[DataContract]
public class users
{
[DataMember] public String userName { get; set; }
}
[DataContract]
public class User
{
/// <summary>登录的用户名</summary>
[DataMember] public string userName;
public DateTime loginTime;
public readonly IChatServiceCallback callback;
public User(string userName, IChatServiceCallback callback)
{
//this.userName = userName;
this.callback = callback;
}
}
//客户端
public interface IChatServiceCallback
{
[OperationContract(IsOneWay = true)]
void ShowLogin(string userName, int userCount);
[OperationContract(IsOneWay = true)]
void ShowSendInfo(string info , string infousername);
[OperationContract(IsOneWay = true)]
void ShowLogout(string userName, int userCount);
[OperationContract(IsOneWay = true)]
void ShowWrongLogin(string userName);
[OperationContract(IsOneWay = true)]
void ShowWrongLogout(string userName);
[OperationContract(IsOneWay = true)]
void ShowUserList(List<User> users);
[OperationContract(IsOneWay = true)]
void ShowPrivateChat(string userName , string text);
}
}
WPF部分
MainWindow.xaml.cs源码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WpfApp_ChatClient.ServiceReference1;
namespace WpfApp_ChatClient
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window, IService1Callback
{
public MainWindow()
{
InitializeComponent();
this.Closing += Window_Closing;
this.btnLogout.IsEnabled = false;
this.btnSend.IsEnabled = false;
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
client.Logout(UserName);
e.Cancel = false;
}
public string UserName;
private Service1Client client;
//登录
private void btnLogin_Click(object sender, RoutedEventArgs e)
{
UserName = textBoxUserName.Text;
if (textBoxUserName.Text == String.Empty)
{
MessageBox.Show("用户名不能为空!!!");
return;
}
InstanceContext context = new InstanceContext(this);
client = new Service1Client(context);
client.Login(textBoxUserName.Text);
serviceTextBlock.Text = "服务端地址:" + client.Endpoint.ListenUri.ToString();
this.dataGrid.ItemsSource = null;
client.LoginList();
this.btnLogin.IsEnabled = false;
this.btnLogout.IsEnabled = true;
this.btnSend.IsEnabled = true;
}
//退出
private void btnLogout_Click(object sender, RoutedEventArgs e)
{
if (textBoxUserName.Text == String.Empty)
{
MessageBox.Show("用户名不能为空!!!");
return;
}
client.Logout(UserName);
userscount.Text = "在线人数:0";
this.btnLogin.IsEnabled = true;
this.btnLogout.IsEnabled = false;
this.btnSend.IsEnabled = false;
}
//发送消息
private void btnSend_Click(object sender, RoutedEventArgs e)
{
if (textBoxSend.Text == String.Empty)
{
MessageBox.Show("发送的消息不能为空!!!");
return;
}
client.sendInfo(textBoxSend.Text, UserName);
textBoxSend.Clear();
}
//显示用户登录
public void ShowLogin(string loginUsername, int userCount)
{
listBoxMessage.Items.Add(loginUsername + "进入大厅。");
userscount.Text = "在线人数:" + userCount.ToString();
}
//显示输入的消息
public void ShowSendInfo(string info, string infousername)
{
listBoxMessage.Items.Add(infousername + ": " + info);
}
//显示用户退出
public void ShowLogout(string userName, int userCount)
{
listBoxMessage.Items.Add(userName + "退出大厅。");
userscount.Text = "在线人数:" + userCount.ToString();
this.dataGrid.ItemsSource = null;
}
public void ShowWrongLogin(string username)
{
MessageBox.Show("用户" + username + "已经存在");
}
public void ShowWrongLogout(string username)
{
MessageBox.Show("用户" + username + "已经退出");
}
private void textBoxSend_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
this.btnSend_Click(sender, e);
}
}
//显示在线用户
public void ShowUserList(User[] users)
{
this.dataGrid.ItemsSource = null;
this.dataGrid.ItemsSource = users;
}
//私聊
public void btnPrivateChat_Click(object sender, RoutedEventArgs e)
{
var temp = dataGrid.SelectedItem;
if (temp == null)
{
return;
}
if (textBoxSend.Text == String.Empty)
{
MessageBox.Show("发送的消息不能为空!!!");
return;
}
User SelectUser = temp as User;
try
{
string SelectName = SelectUser.userName;
client.PrivateChat(UserName, SelectName, textBoxSend.Text);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "私发出现错误");
}
}
public void ShowPrivateChat(string userName, string text)
{
listBoxMessage.Items.Add(userName + "发给你: " + text);
textBoxSend.Clear();
}
}
}
MainWindow.xaml源码
<Window x:Class="WpfApp_ChatClient.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp_ChatClient"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"></ColumnDefinition>
<ColumnDefinition Width="500"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<DockPanel Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="3" Background="Cornsilk"
Margin="5 5 0 5">
<Label Content="用户名:"/>
<TextBox Name="textBoxUserName" Width="100" VerticalAlignment="Center"/>
<Button Name="btnLogin" Content="登录" Width="60" Margin="10 0 10 0" Click="btnLogin_Click"/>
<Button Name="btnLogout" Content="退出" Width="60" Margin="10 0 10 0" Click="btnLogout_Click"/>
<TextBlock Name="serviceTextBlock" Text="服务端地址:" Margin="5 0 0 0" VerticalAlignment="Center"/>
</DockPanel>
<Grid Name="ChatRooms" Grid.Row="1" Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="聊天室" Background="Beige" TextAlignment="Center"></TextBlock>
<Grid Grid.Row="1" >
<ListBox Name="listBoxRooms" Background="AntiqueWhite" ScrollViewer.VerticalScrollBarVisibility="Visible"/>
</Grid>
</Grid>
<Grid Name="chatRoom" Grid.Row="1" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
</Grid.RowDefinitions>
<ListBox Name="listBoxMessage" Background="White" Grid.Row="0" ScrollViewer.VerticalScrollBarVisibility="Visible"/>
<DockPanel Grid.Row="1" Background="AliceBlue" Margin="0 5 0 5" >
<Button Name="btnPrivateChat" Content="私发" Margin="5 0 0 0" Width="80" Click="btnPrivateChat_Click"/>
<TextBlock Text="聊天:" Margin="5 0 0 0 " DockPanel.Dock="Left" VerticalAlignment="Center"/>
<Button Name="btnSend" Content="发送" Width="40" DockPanel.Dock="Right" Margin="5 0 5 0" Click="btnSend_Click"/>
<TextBox Name="textBoxSend" KeyDown="textBoxSend_KeyDown"/>
</DockPanel>
</Grid>
<Grid Name="chatUser" Grid.Row="1" Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Name="userscount" Grid.Row="0" Text="在线人数: 0" Background="Beige" TextAlignment="Center"/>
<DataGrid Name="dataGrid" Grid.Row="1" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding userName}" ClipboardContentBinding="{x:Null}" Header="在线用户"/>
<!-- <DataGridTextColumn Binding="{Binding loginTime}" ClipboardContentBinding="{x:Null}" Header="登录时间"/>-->
</DataGrid.Columns>
</DataGrid>
</Grid>
</Grid>
</Window>
界面如下
操作
点击右侧在线用户,就可以私发消息