基于Socket的通信

2007年12月03日 星期一 下午 05:46

其实以前也看过这个东西,不过当时人太菜了,没搞清楚...现在要好一点了,所以再做了一遍.

这回一共用了两种方法做,一种是用的Socket,

写了个类.其中方法有:string Listen(IPAddress ipAddress),void Send(EndPoint point, string message)

/// <summary>
        /// 侦听指定端口传入的信息,并返回
        /// </summary>
        /// <param name="ipAddress">要侦听的Ip,传入null为侦听所有Ip</param>
        /// <returns></returns>
        public string Listen(IPAddress ipAddress)
        {
            EndPoint point;
            if (ipAddress == null)
            {
                point = new IPEndPoint(IPAddress.Any, Port);
            }
            else
            {
                point = new IPEndPoint(ipAddress, Port);
            }

            Socket s = CreateSocket();
            s.Bind(point);
            s.Listen(0);
            Socket temp = s.Accept();
            this.Point = temp.LocalEndPoint;
            s.Close();
            string recvStr = "";
            if (temp != null)
            {
                recvStr = Receive(temp);

                temp.Close();
            }
            return recvStr;
        }

        /// <summary>
        /// 发送信息
        /// </summary>
        /// <param name="address">接收端的Ip信息</param>
        /// <param name="message">发送的内容</param>
        public void Send(EndPoint point, string message)
        {
            Socket so = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            so.Connect(point);

            byte[] bs = Encoding.UTF8.GetBytes(message);
            so.Send(bs, bs.Length, SocketFlags.None);
            so.Close();
        }

        #region 私有方法

        /// <summary>
        /// 接收侦听端口的信息
        /// </summary>
        /// <param name="temp"></param>
        /// <returns></returns>
        private string Receive(Socket temp)
        {
            byte[] recvBytes = new byte[1024];
            int bytes;
            bytes = temp.Receive(recvBytes, recvBytes.Length, SocketFlags.None);
            return Encoding.UTF8.GetString(recvBytes, 0, bytes);
        }

        /// <summary>
        /// 创建一个Socket
        /// </summary>
        /// <returns></returns>
        private Socket CreateSocket()
        {
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            return socket;
        }

        #endregion

这样,在服务端启动的时候,启动一个线程.调用下面这个方法:

private void GetValues()
        {
            MySocket mySocket = new MySocket();
            string va = mySocket.Listen(null);

            SetValue(va);

            thmain = new Thread(GetValues);
            thmain.Start();
        }

private void SetValue(string values)
        {
            if (listBox1.InvokeRequired)
            {
                listDelete li = new listDelete(SetValue);
                this.Invoke(li, new object[] { values });
            }
            else
            {
                //string v = string.Empty;
                if (values.StartsWith("@Ip"))
                {
                    values = values.Replace("@Ip", "");
                    listBox2.Items.Add(values);
                }
                else
                {
                    listBox1.Items.Add(values);
                    listBox1.SelectedIndex = listBox1.Items.Count - 1;
                }
            }
        }

这样,在服务端就一直侦听,当然是通过线程来完成的,不然会卡起不动,用到线程的话就会产生线程间操作控件的问题,SetValue就是解决它的.

客户端加载时,调用.Send(serverIp, "@Ip" + Dns.GetHostAddresses(Dns.GetHostName())[0].ToString());,向服务器发送一个本机的IP,同时,调用侦听方法..一直侦听,.发送的话就调用发送方法.

不过这里运行后产生了个问题,在运行的时候,当服务端侦听后.客户端就不能侦听了.异常信息是不能同时绑定一个端口.

后来换了个实现方法:

只是改了类中的两个方法而已,.

public string Listen(string ip)
        {
            TcpListener tcpLis = new TcpListener(IPAddress.Any, 8000);
            tcpLis.Start();
            TcpClient client = tcpLis.AcceptTcpClient();

            NetworkStream nsStream = client.GetStream();
            StreamReader srRead = new StreamReader(nsStream);

            string va = srRead.ReadLine();

            tcpLis.Stop();
            client.Close();
            nsStream.Close();
            srRead.Close();
            return va;
        }

        public void Send(string ip, string message)
        {
            TcpClient tcpClient = new TcpClient(Dns.GetHostEntry(IPAddress.Parse(ip)).HostName, 8000);
            NetworkStream nsStream = tcpClient.GetStream();
            StreamWriter swWriter = new StreamWriter(nsStream);
            swWriter.WriteLine(message);
            swWriter.Flush();

            tcpClient.Close();
            nsStream.Close();
            swWriter.Close();
        }

这样做出来就完全可以了,,客户端和服务端都可能收发信息,像QQ一样,

就写到这里,,今天很累//

posted @ 2008-02-01 10:51  point.deng  阅读(305)  评论(0编辑  收藏  举报