socket入门教程

Server.cs   服务端程序

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Net.Sockets;

namespace SocketTest
{
    public partial class Server : Form
    {
        Thread serverThread; //服务端线程
        Thread clientThread; //客户端线程
        Socket serverSocket; //服务端socket
        Socket clientSocket; //客户端socket

        public Server()
        {
            InitializeComponent();
        }

        private void ServerStart()
        {
            //创建IPEndPoint实例
            IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 6001);
            //创建一个套接字
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //将所创建的套接字与IPEndPoint绑定
            serverSocket.Bind(ipep);
            //设置套接字为收听模式
            serverSocket.Listen(10);

            /**
             * 通过serverSocket.Accept()来接收客户Socket的连接请求,
             * 在这里用循环可以实现该线程实时侦听,而不是只侦听一次。
             * 当程序运行serverSocket.Accept()时,会等待,直到有客户端Socket发起连接请求时,
             * 获取该客户Socket,如上面的clientSocket。在这里我用多线程来实现与多个客户端Socket的连接和通信,
             * 一旦接收到一个连接后,就新建一个线程,执行ReceiveData功能来实现信息的发送和接收。
             */
            while (true)
            {
                try
                {
                    //在套接字上接收接入的连接
                    clientSocket = serverSocket.Accept();
                    clientThread = new Thread(new ThreadStart(ReceiveData));
                    clientThread.Start();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("listening Error: " + ex.Message);
                }
            }
        }

        /**
         * 通过IPEndPoint clientep = (IPEndPoint)s.RemoteEndPoint;
         * 我们可以获取连接上的远程主机的端口和IP地址,如果想查询该主机的其它属性如主机名等,
         * 可用于上一篇讲的Dns.GetHostByAddress(string ipAddress)来返回一个IPHostEntry对象,就可以得到。
         * 另外我们要注意的是,通过Socket发送信息,必须要先把发送的信息转化成二进字进行传输,
         * 收到信息后也要把收到的二进字信息转化成字符形式,
         * 这里可以通过Encoding.ASCII.GetBytes(welcome);和Encoding.ASCII.GetString(buffer).Substring(0, bufLen);来实现。
         * 以上就是服务端Socket侦听模式的实现,只要有远程客户端Socket连接上后,就可以轻松的发送信息和接收信息了。
         * 下面我们来看看客户端Socket是怎么连接上服务器的。
         **/
        private void ReceiveData()
        {
            bool keepalive = true;
            Socket s = clientSocket;
            Byte[] buffer = new Byte[1024];
            //根据收听到的客户端套接字向客户端发送信息
            IPEndPoint clientep = (IPEndPoint)s.RemoteEndPoint;
            this.Invoke(new MethodInvoker(() =>
            {
                lstServer.Items.Add("Client:" + clientep.Address + "(" + clientep.Port + ")");
            }));
            string welcome = "Welcome to my test sever ";
            byte[] data = new byte[1024];
            data = Encoding.ASCII.GetBytes(welcome);
            s.Send(data, data.Length, SocketFlags.None);
            while (keepalive)
            {
                //在套接字上接收客户端发送的信息
                int bufLen = 0;
                try
                {
                    bufLen = s.Available;
                    s.Receive(buffer, 0, bufLen, SocketFlags.None);
                    if (bufLen == 0)
                        continue;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Receive Error:" + ex.Message);
                    return;
                }
                clientep = (IPEndPoint)s.RemoteEndPoint;
                string clientcommand = System.Text.Encoding.ASCII.GetString(buffer).Substring(0, bufLen);
                this.Invoke(new MethodInvoker(() =>
                {
                    lstServer.Items.Add(clientcommand + "(" + clientep.Address + ":" + clientep.Port + ")");
                }));
            }
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            serverThread = new Thread(new ThreadStart(ServerStart));
            serverThread.Start();
            lstServer.Items.Add("Server Start .....");
        }
    }
}

Client.cs(客户端程序)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace Client
{
    public partial class Client : Form
    {
        Socket clientSocket;
        Thread clientThread;

        public Client()
        {
            InitializeComponent();
        }

        /**
         * 客户端Socket连接相对来说比较简单了,另外说明一下,在执行客户端连接前,服务端Socket侦听必须先启动,
         * 不然会提示服务器拒绝连接的信息。
         * 客户端的发送信息和接收信息跟服务器的接收发送是一样的,只不过一个是侦听模式而另一个是连接模式。
         * 另外提一下,这里服务端开启侦听服务、客户端连接服务端都采用线程方式来实现,这样服务端能够跟多个客户端同时通信,不用等候,
         * 当然还有另外一种方式可以实现那就是异步socket.
         */
        private void ConnectToServer()
        {
            byte[] data = new byte[1024];
            //创建一个套接字
            IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6001);
            clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //将套接字与远程服务器地址相连
            try
            {
                clientSocket.Connect(ipep);
            }
            catch (SocketException ex)
            {
                MessageBox.Show("connect error: " + ex.Message);
                return;
            }
            while (true)
            {
                //接收服务器信息
                int bufLen = 0;
                try
                {
                    bufLen = clientSocket.Available;
                    clientSocket.Receive(data, 0, bufLen, SocketFlags.None);
                    if (bufLen == 0)
                    {
                        continue;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Receive Error:" + ex.Message);
                    return;
                }
                string clientcommand = System.Text.Encoding.ASCII.GetString(data).Substring(0, bufLen);
                this.Invoke(new MethodInvoker(() =>
                {
                    lstClient.Items.Add(clientcommand);
                }));
                //clientSocket.Shutdown(SocketShutdown.Both);
                //clientSocket.Close();
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            clientThread = new Thread(new ThreadStart(ConnectToServer));
            clientThread.Start();
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            //向服务器发送信息
            byte[] data = new byte[1024];
            data = Encoding.ASCII.GetBytes(txtClient.Text);
            clientSocket.Send(data, data.Length, SocketFlags.None);
        }
    }
}

 

posted on 2013-08-05 11:29  larryle  阅读(339)  评论(0编辑  收藏  举报