上一篇文章实现了注册和登录功能,其实只要能够登录的客户端程序,自登录的那一刻起就需要连接到服务器。所以本篇文章要编写CIM服务端程序,通信的原理在这一系列文章的第9篇已经介绍过,服务端程序就是从基础的通讯原理上针对CIM项目的业务逻辑进行扩展。
上一篇文章还有一点没有提到,就是对数据操作时,表中的数据类型不能为text,否则会报数据类型不兼容的错误:
解决方法就是重新修改表中字段类型为varchar类型。
界面搭建
首先要搭建服务端程序的界面。界面布局如下图所示:
布局中有一个TextBox和一个ListBox用于显示上下线记录和在线账号列表。label3用于显示当前在线人数。
首先我们需要添加五个字段作为全局变量:
//服务器IP
private string ip = "127.0.0.1";
//应用程序端口
private int port = 1234;
//用于监听的Socket对象
Socket listenSocket;
//用于保存连接到服务端socket的客户端socket,使用账号作为唯一标识
Dictionary dic_socket = new Dictionary();
//用于分隔账号和消息内容的分隔标志
//因为客户端发送消息时,必须指定发送的目标账号,所以需要用分隔标志将账号和内容分开
private string splitFlag = "&^%$#";
下面是“启动CIM服务”按钮的点击事件:
private void button1_Click(object sender, EventArgs e)
{
//1.new出socket对象
listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//2.绑定IP和端口
listenSocket.Bind(new IPEndPoint(IPAddress.Parse(ip), port));
//3.设置连接数量
listenSocket.Listen(1000);
//4.开启接收,新线程保证界面不卡
Thread acceptThread = new Thread(acceptClientSocket);
acceptThread.IsBackground = true;
acceptThread.Start();
//界面的提示信息
label1.Text = "已启动CIM服务!";
label1.ForeColor = Color.Green;
button1.Enabled = false;
}
然后是接收客户端连接的方法:
private void acceptClientSocket()
{
//死循环保证可以连接多个客户端socket
while (true)
{
//收到客户端连接后返回一个用于和客户端通信的socket对象 需要保存到字典中
Socket clientSocket = listenSocket.Accept();
byte[] buffer = new byte[1024];
//客户端连接上后,客户端必须主动发送自己的账号,所以这里需要接受这个账号
int len = clientSocket.Receive(buffer);
string clientAccount = Encoding.UTF8.GetString(buffer, 0, len);
//将用于和客户端通信的socket保存到字典中,客户端账号作为键,socket作为值
dic_socket.Add(clientAccount, clientSocket);
//界面的提示信息
upAnddown.AppendText("账号" + clientAccount + "在" + DateTime.Now.ToString() + "上线\r\n");
label3.Text = (int.Parse(label3.Text)+1).ToString();
online_list.Items.Add(clientAccount.ToString());