根据以上总结的客户端与服务器端的通信过程,
我们先来写一个服务器端。
private void btnOpen_Click(object sender, EventArgs e)
{
//创建一个Socket对象
Socket severSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//绑定端口和IP
IPEndPoint endPoint=new IPEndPoint(IPAddress.Parse(txtIP.Text),int.Parse(txtPort.Text));
severSocket.Bind(endPoint);
//开始监听
severSocket.Listen(10);
//开始连接
//主线程会在这里一直阻塞,直到连接到一个客户端
//返回值是一个代理通信Socket对象
Socket socket = severSocket.Accept();
txtLog.Text = "已成功连接:"+socket.RemoteEndPoint+"\r\n" + this.txtLog.Text;
//发送消息
byte[] myBuffer=Encoding.Default.GetBytes(DateTime.Now.ToString());
socket.Send(myBuffer);
txtLog.Text = "消息已成功发送\r\n" + this.txtLog.Text;
//关闭代理Socket
socket.Shutdown(SocketShutdown.Both);
socket.Close();
//关闭总的Socket
txtLog.Text = "连接已断开\r\n" + this.txtLog.Text;
severSocket.Close();
}
这里只要根据图上的步骤一步一步来基本没什么大问题。
只需要注意两点:
(1)Socket对象的Accept方法会阻塞线程,如果在主线程执行会出现卡死的现象,直到你连接到客户端。
(2)关于txtLog.Text的写法,可能有人会有疑问,其实是很简单的一个道理,
将最新的消息显示在头上,如果显示数据很多的话,优势就很明显了,不必总是往下滚滚动条。
显示效果如下:
这里可以使用多线程方法来解决刚才卡死的问题
创建一个新的线程来执行阻塞等待Accept方法
代码如下:
private void btnOpen_Click(object sender, EventArgs e)
{
//创建一个Socket对象
Socket severSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//绑定端口和IP
IPEndPoint endPoint=new IPEndPoint(IPAddress.Parse(txtIP.Text),int.Parse(txtPort.Text));
severSocket.Bind(endPoint);
//开始监听
severSocket.Listen(10);
//用别的线程来连接客户端
ThreadPool.QueueUserWorkItem(new WaitCallback(CallBackSocket),severSocket);
}
public void CallBackSocket(object obj)
{
//将参数obj强转成Socket类型
Socket severSocket = (Socket)obj;
//开始连接
//主线程会在这里一直阻塞,直到连接到一个客户端
//返回值是一个代理通信Socket对象
//可能连接多个客户端,需要循环
while (true)
{
Socket socket = severSocket.Accept();
txtLog.Text = "已成功连接:" + socket.RemoteEndPoint + "\r\n" + this.txtLog.Text;
//发送消息
byte[] myBuffer = Encoding.Default.GetBytes(DateTime.Now.ToString());
socket.Send(myBuffer);
txtLog.Text = "消息已成功发送\r\n" + this.txtLog.Text;
//关闭代理Socket
socket.Shutdown(SocketShutdown.Both);
socket.Close();
//关闭总的Socket
txtLog.Text = "连接已断开\r\n" + this.txtLog.Text;
//severSocket.Close();
}
}
如果出现跨线程访问控件的错误,请查看之前的多线程学习博客里的解决方案