记得张博士曾跟我说过,对于大数据量的通信软件,应该将TCP和UDP结合起来。TCP准确率高,但是传输速度低,而UDP正好相反。

  现在就写写Socket通信的具体实施吧!

  先说服务器端:

首先是使用Socket类型变量,启动服务器。启动需要知道本机的IP地址和一个空闲的端口号。

IP地址和端口号构成一个网络节点,使用Socket绑定网络节点即可;

 public void connection()
        {
            //定义一个套接字用于监听客户端发来的信息  包含3个参数(IP4寻址协议,流式连接,TCP协议)
            socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //服务端发送信息 需要1个IP地址和端口号
            IPAddress ipaddress = this.ipAddress; //获取文本框输入的IP地址
            //将IP地址和端口号绑定到网络节点endpoint上 
            IPEndPoint endpoint = new IPEndPoint(ipaddress, this.portNum); //获取文本框上输入的端口号
            //监听绑定的网络节点
            socketWatch.Bind(endpoint);
………………

这样就创建了一个通信的端口,如果本机IP地址错误,就会报错。

当通信端口创建成功后,就需要开启监听客户端是否连接这一个功能。

socketWatch.Accept();

这就是开启监听客户端是否有连接的那句话,他的返回值是一个Socket,这个返回值是有用的需要保存下来后面使用。因此是这样写的

 socConnection = socketWatch.Accept();  //socConnection 是一个Socket类型的变量

注意:监听是一个持续的过程,需单独开启一个线程,后台运行。

        private void WatchConnecting()
        {
            while (true)  //持续不断监听客户端发来的请求
            {
                socConnection = socketWatch.Accept();
                IsConnected = "已连接";                  //注意大小写
            }
        }

总的开启监听的代码如下:

        Thread threadWatch = null; //负责监听客户端的线程
        Socket socketWatch = null; //负责监听客户端的套接字
        //创建一个套接字,负责和客户端通信
        Socket socConnection;

        public Socket SocConnection
        {
            get { return socConnection; }
            set { socConnection = value; }
        }

        /// <summary>
        /// 启动服务器,开始监听客户端
        /// </summary>
        public void connection()
        {
            //定义一个套接字用于监听客户端发来的信息  包含3个参数(IP4寻址协议,流式连接,TCP协议)
            socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //服务端发送信息 需要1个IP地址和端口号
            IPAddress ipaddress = this.ipAddress; //获取文本框输入的IP地址
            //将IP地址和端口号绑定到网络节点endpoint上 
            IPEndPoint endpoint = new IPEndPoint(ipaddress, this.portNum); //获取文本框上输入的端口号
            //监听绑定的网络节点
            socketWatch.Bind(endpoint);
            //将套接字的监听队列长度限制为20
            socketWatch.Listen(20);
            //创建一个监听线程 
            threadWatch = new Thread(WatchConnecting);
            //将窗体线程设置为与后台同步
            threadWatch.IsBackground = true;
            //启动线程
            threadWatch.Start();
        }
        private void WatchConnecting()
        {
            while (true)  //持续不断监听客户端发来的请求
            {
                socConnection = socketWatch.Accept();
                IsConnected = "已连接";                  //注意大小写
            }
        }

这样,服务器就启动了,下面就在等待客户端连接了。。。

连接是否成功的标志是

socketWatch.Accept()他的返回值不是null。
也就是时刻监视
socConnection 是不是null,如果不是null就证明有客户端连接,下面就是接受客户端消息的工作了。
通信工作是有Socket类型变量完成的,这个socket变量不是重新声明的而是监听成功后的返回值,否则的话,怎么能发送到已连接的客户端呢?

使用Socket.receive(arrServerRecMsg)接收消息,接收到的消息放在arrServerRecMsg缓存区中,返回接收到的字节数。byte[] arrServerRecMsg = new byte[1024 * 1024];
int length = socketServer.Receive(arrServerRecMsg);
然后将机器接收到的数组转换成人可以读的数组。
this.receiveMsg = Encoding.UTF8.GetString(arrServerRecMsg, 0, length);这样接收消息就完成了。
       public void communicate()
        {
            //创建一个通信线程 
            ParameterizedThreadStart pts = new ParameterizedThreadStart(ServerRecMsg);
            Thread thr = new Thread(pts);
            thr.IsBackground = true;
            //启动线程
            thr.Start(socConnection);
        }
        /// <summary>
        /// 接收客户端发来的消息
        /// </summary>
        /// <param name="socketClientPara"></param>
        public void ServerRecMsg(object socketClientPara)
        {
            socketServer = socketClientPara as Socket;
            while (true)
            {
                //创建一个内存缓冲区 其大小为1024*1024字节  即1M
                byte[] arrServerRecMsg = new byte[1024 * 1024];
                //将接收到的信息存入到内存缓冲区,并返回其字节数组的长度
                int length = socketServer.Receive(arrServerRecMsg);
                //将机器接受到的字节数组转换为人可以读懂的字符串
                this.receiveMsg = Encoding.UTF8.GetString(arrServerRecMsg, 0, length);
                MsgIn *= -1;
            }
        }

以上是接受消息的代码,调用的时候是调用communicate这个方法。

下面说说客户端的程序:

客户端的绑定也是

Socket.connect(endpoint),即可;endpoint = new IPEndPoint(ipaddress, this.portNum);
如果服务器端长时间没有反应,就会弹出提示对话框。
这时,正常的话就是可以连接成功,服务器端的返回值也就不再是null。服务器已经进入时刻等待接收消息的状态。
这就算是建立起了一条可以通信的通道。

发送消息的方式也很简单。就是下面的这个函数
public void sendaMsg()
        {
            //将输入的内容字符串转换为机器可以识别的字节数组
            byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(sendMsg);
            //调用客户端套接字发送字节数组
            socketClient.Send(arrClientSendMsg);
        }

值得一提的是,里面的socketClient也是一个Socket对象。这与之前连接服务器的Socket是同一个对象。。。
这样就完成了通信。

接下来开始做客户端发送消息的程序!