学习一个新的东西,首先要知道其原理,对于Sockets的学习,可先看一下文档:http://blog.csdn.net/hulihui/article/details/3230503#st 点击打开链接
刚开始是写代码实现了一个客户端和服务器的通讯,后来完善代码,实现了多个客户端与服务器端的通讯,由于原理是差不多的,这里就直接介绍多个客户端与服务器进行通讯。
第一部分 窗体设计
1.服务器端
2.客户端
第二部分 代码
1.服务器端:
– 申请一个socket (socketWatch)用来监听的
– 绑定到一个IP地址和一个端口上
– 开启侦听,等待接授客户端的连接
– 当有连接时创建一个用于和连接进来的客户端进行通信的socket(socketConnection)
– 即续监听,等侍下一个客户的连接
- //服务器端
- using System.IO;
- using System.Net;
- using System.Threading;
- using System.Net.Sockets;
- namespace SocketsServer
- {
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- Socket socketWatch = null;
- Thread threadWatch = null;
- private void startconn_Click(object sender, EventArgs e)
- {
- socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- IPAddress ipaddress = IPAddress.Parse(localip.Text.Trim());
- IPEndPoint endpoint = new IPEndPoint(ipaddress, int.Parse(porttext.Text.Trim()));
- socketWatch.Bind(endpoint);
- socketWatch.Listen(10);
- threadWatch = new Thread(WatchingConn);
- threadWatch.IsBackground = true;
- threadWatch.Start();
- this.Invoke(new Action(() =>
- {
- recmsg.AppendText("开始对客户端进行监听!" + "\r\n");
- }
- ));
- }
- //保存了服务器端所有负责和客户端通信发套接字
- Dictionary<string, Socket> dictSocket = new Dictionary<string, Socket>();
- //保存了服务器端所有负责调用通信套接字.Receive方法的线程
- Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>();
- //Socket socConn = null;
- private void WatchingConn(object obj)
- {
- while (true)
- {
- Socket socConn = socketWatch.Accept();
- this.Invoke(new Action(() => {
- //向下拉项中添加一个客户端的ip端口字符串,作为客户端的唯一标识
- iptext.Items.Add(socConn.RemoteEndPoint.ToString());
- }));
- 将与客户端通信的套接字对象sokConn添加到键值对集合中,并以客户端IP端口作为键
- dictSocket.Add(socConn.RemoteEndPoint.ToString(), socConn);
- ParameterizedThreadStart pts = new ParameterizedThreadStart(RecMsg);
- Thread trd = new Thread(pts);
- trd.IsBackground = true;
- trd.Start(socConn);
- dictThread.Add(socConn.RemoteEndPoint.ToString(), trd);
- this.Invoke(new Action(()=>
- {
- recmsg.AppendText("客户端连接成功!" + "\r\n");
- }
- ));
- }
- }
- private void RecMsg(object socketClientPara)
- {
- Socket socketRec = socketClientPara as Socket;
- while (true)
- {
- byte[] arrRecMsg = new byte[1024 * 1024];
- //int length = socketClient.Receive(arrRecMsg);//......wrong......
- int length = -1;
- try
- {
- length = socketRec.Receive(arrRecMsg);
- }
- catch (SocketException ex)
- {
- MessageBox.Show("异常:" + ex.Message);
- //从通信套接字集合中删除被中断连接的通信套接字对象
- dictSocket.Remove(socketRec.RemoteEndPoint.ToString());
- //从通信线程结合中删除被终端连接的通信线程对象
- dictThread.Remove(socketRec.RemoteEndPoint.ToString());
- //从列表中移除被中断的连接 ip:Port
- iptext.Items.Remove(socketRec.RemoteEndPoint.ToString());
- break;
- }
- catch (Exception ex)
- {
- MessageBox.Show("异常:" + ex.Message);
- break;
- }
- string str = Encoding.UTF8.GetString(arrRecMsg, 0, length);
- this.Invoke(new Action(() => {
- recmsg.AppendText(iptext.Text + ":\r\n" + GetTime() + "\r\n" + str + "\r\n");
- }));
- Thread.Sleep(10);
- }
- }
- private DateTime GetTime()
- {
- DateTime getTime = new DateTime();
- getTime = DateTime.Now;
- return getTime;
- }
- private void SendMsg(string sendMsg)
- {
- if (string.IsNullOrEmpty(iptext.Text))
- {
- MessageBox.Show("请选择通信IP!");
- }
- else
- {
- byte[] strSendMsg = Encoding.UTF8.GetBytes(sendMsg);
- string strClientKey = iptext.Text;//通过Key匹配对应ip地址的客户端
- dictSocket[strClientKey].Send(strSendMsg);
- this.Invoke(new Action(() =>
- {
- recmsg.AppendText("服务器:" + "\r\n" + GetTime() + "\r\n" + sendMsg + "\r\n");
- }));
- sendmsg.Text = null;
- }
- }
- private void sendok_Click(object sender, EventArgs e)
- {
- SendMsg(sendmsg.Text.Trim());
- }
- }
- }
– 申请一个socket
– 连接服务器(指明IP地址和端口号)
- //客户端
- using System.IO;
- using System.Net;
- using System.Net.Sockets;
- using System.Threading;
- namespace SocketsClient
- {
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- Socket socketWatch = null;
- Thread threadWatch = null;
- private void startconn_Click(object sender, EventArgs e)
- {
- socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- IPAddress address = IPAddress.Parse(iptext.Text.Trim());
- IPEndPoint endpoint = new IPEndPoint(address, int.Parse(porttext.Text.Trim()));
- socketWatch.Connect(endpoint);
- // socketWatch.Bind(endpoint);//...报错(服务器是Bind,客户端是Connect)...
- threadWatch = new Thread(RecMsg);
- threadWatch.IsBackground = true;
- threadWatch.Start();
- }
- private void RecMsg(object obj)
- {
- while (true)
- {
- byte[] arrRecMsg = new byte[1024 * 1024];
- int length = socketWatch.Receive(arrRecMsg);
- string str = Encoding.UTF8.GetString(arrRecMsg, 0, length);
- this.Invoke(new Action(() => {
- recmsg.AppendText("服务器:" + "\r\n" + GetTime() + "\r\n" + str + "\r\n");
- }));
- }
- }
- private DateTime GetTime()
- {
- DateTime getTime = new DateTime();
- getTime = DateTime.Now;
- return getTime;
- }
- private void SendMsg(string sendMsg)
- {
- byte[] strSenMsg = Encoding.UTF8.GetBytes(sendMsg);
- socketWatch.Send(strSenMsg);
- this.Invoke(new Action(() =>
- {
- recmsg.AppendText("客户端:" + "\r\n" + GetTime() + "\r\n" + sendMsg + "\r\n");
- }));
- sendmsg.Text = null;
- }
- private void sendok_Click(object sender, EventArgs e)
- {
- SendMsg(sendmsg.Text.Trim());
- }
- }
- }