初窥SOCKET

一、简介   

      随着WEB技术的发展,很多本是用Sockets完成的功能,基本上可以用WEB技术来替代了,Sockets通信技 术逐渐被人们遗忘,而Sockest的应用却也有它独有的优势。网络服务如Internet时间同步、IM工具如MSN与QQ、短信网关如中国移动、中国联通等都采用的是SOCKETs,在信息化发达的今天,很多也想着利用SOCKETs来开发出属于自己的通信工具。

      DONET的System.Net.Sockets命名空间类中封闭了大量的Socket类,此命名空间中用简单的方法对复杂的Sockets进行了连接与通讯。我们一起来建立一个基于System.Net.Sockets的通用类库,并基于此学习一下如何使用该类库。

      开发环境:Microsoft Framework 2.0

      开发工具:Microsoft Visual Studio 2008

 

二、创建

      1、创建一个名为WFASocketsSolution的空白解决方案并在该方案中创建名为SocketsLib的类库及SocketFactory类。     

创建WFASocketsSolution解决方案

创建名为SocketsLib的类库

     
         2、在该解决方案下创建一个名为WFASocketsSample的Windows窗体应用程序项目并将其设为启动项目

 创建WFASocketsSample窗体项目 

    3、在SocketsLib项目中新建名为SocketsConnection的类,为Sockets的连接类,并在此类中添加NetWorkStream和ConnectionName。分别表示一个连接的名字和它包含的NetWorkStream。

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
namespace SocketsLib
{
    public class SocketsConnection
    {
        #region private fields
        private NetworkStream _networkStream;
        private String _connectionName;
        #endregion
        #region public property
        public NetworkStream NetworkStream
        {
            get { return _networkStream; }
            set { _networkStream = value; }
        }
        public String ConnectionName
        {
            get { return _connectionName; }
            set { _connectionName = value; }
        }
        #endregion
        #region Constructor
        public SocketsConnection(NetworkStream networkStream,string connectionName)
        {
            this._networkStream = networkStream;
            this._connectionName = connectionName;
        }
        public SocketsConnection(NetworkStream networkStream)
            : this(networkStream, string.Empty)
        {
        }
        #endregion
    }
}
    4、新建一个继承自List<SocketsConnection>的ConnectionCollection类
using System;
using System.Collections.Generic;
using System.Text;
namespace SocketsLib
{
    public class ConnectionCollection:List<SocketsConnection>
    {
    }
}

    5、新建一名为SocketsServer的类,用于侦听网络连接

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
namespace SocketsLib
{
    public class SocketsServer
    {
        #region private fields
        private ConnectionCollection _connections;
        private TcpListener _listener;
        #endregion
        #region public properties
        public ConnectionCollection Connections
        {
            get { return _connections; }
            set { _connections = value; }
        }
        public TcpListener Listener
        {
            get { return _listener; }
            set { _listener = value; }
        }
        #endregion
        #region constructor
        public SocketsServer(TcpListener listener)
        {
            this._connections = new ConnectionCollection();
            this._listener = listener;
        }
        #endregion
        #region public function
        public void Start()
        {
            while (true)
            {
                if (_listener.Pending())
                {
                    TcpClient client = _listener.AcceptTcpClient();
                    NetworkStream stream = client.GetStream();
                    this._connections.Add(new SocketsConnection(stream));
                }
            }
        }
        #endregion
    }

    6、在SocketsFactory类中声明一个私有变量_serverListenThread,并加入StartServer方法。当执行此方法时,初始化_ serverListenThread并在此线程中开始侦听网络连接

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace SocketsLib
{
    public class SocketsFactory
    {
        #region private fields
        System.Threading.Thread _serverListenThread;
        #endregion
        #region public function
        public void StartServer(int port)
        {
            TcpListener listener = new TcpListener(IPAddress.Any, port);
            listener.Start();
            SocketsServer server = new SocketsServer(listener);
            _serverListenThread = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(server.Start));
            _serverListenThread.Start();
        }
        #endregion
    }
}

    6、做到此处,需要做一个测试,看线程是否能够正常的工作,在窗体项目中添加一窗体类SampleForm,并在SampleForm_Load方法中添加如下代码

using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WFASocketsSample
{
    public partial class SampleForm : Form
    {
        public SampleForm()
        {
            InitializeComponent();
        }
        private void SampleForm_Load(object sender, EventArgs e)
        {
            SocketsLib.SocketsFactory factory = new SocketsLib.SocketsFactory();
            factory.StartServer(1979);
        }
    }
}

   在SocketsServer中的Start中加了断点后进行Debug,得到下图,我们可以看到线程已经启动,并开始监听了。

在断点处中断

     7、下面我们启动另外一个Visual Studio 2008实例,创建一个名为WFASocketsTestSolution的解决方案,将SocketsLib项目包含进来并创建一个名为WFASocketsTest的Windows应用程序

创建WFASocketsTestSolution

      8、在SocketsLib项目中创建名为Client的类

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace SocketsLib
{
    public class Client
    {
        #region public fields
        public const int CONNECTTIMEOUT = 10;
        public SocketsConnection connection;
        #endregion
        #region constructor
        public Client()
        {
        }
        #endregion
        #region public function
        public static SocketsConnection StartClient(IPAddress ipaddress, int port)
        {
            TcpClient client = new TcpClient();
            client.SendTimeout = CONNECTTIMEOUT;
            client.ReceiveTimeout = CONNECTTIMEOUT;
            client.Connect(ipaddress, port);
            return new SocketsConnection(client.GetStream());
        }
        #endregion
    }
}

     9、在SocketFactory中加入StartClient函数

 public SocketsConnection StartClient(IPAddress ip, int port)
        {
            return Client.StartClient(ip, port);
        }
     10、在项目的窗体类的TestForm_Load方法中加入如下代码,然后,先执行WFASocketsSample项目,然后执行此项目,如果没有报错,则表明连接成功。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using SocketsLib;
namespace WFASocketsTest
{
    public partial class TestForm : Form
    {
        private SocketsConnection _connection;
        public TestForm()
        {
            InitializeComponent();
        }
        private void TestForm_Load(object sender, EventArgs e)
        {
            SocketsFactory factory = new SocketsFactory();
            _connection = factory.StartClient(System.Net.IPAddress.Parse("192.168.0.2"), 1979);
        }
    }
}

    11、OK,现在客户端可以连上服务端了,下面,我们就开始构建有我们能看得见摸得着的功能——发送信息。但可以看得出,目前我们还未有任何发送信息的方法。所以,我们在SocketsFactory类中构建一个发送消息的静态方法,

 #region static function
        public static void SendMessage(string message, SocketsConnection connection)
        {
            byte[] buffer = Encoding.UTF8.GetBytes(message);
            connection.NetworkStream.Write(buffer, 0, buffer.Length);
        }
        #endregion

    12、现在我们可以利用此方法来发送消息了。当然,在测试之前,我们要在服务器端的侦听模块中加入侦听信息的功能                                 

public void Listenning()
        {
            while (true)
            {
                System.Threading.Thread.Sleep(2000);
                foreach (SocketsConnection connection in this._connections)
                {
                    if (connection.NetworkStream.CanRead && connection.NetworkStream.DataAvailable)
                    {
                        byte[] buffer = new byte[1024];
                        int count = connection.NetworkStream.Read(buffer, 0, buffer.Length);
                        Console.Write(Encoding.UTF8.GetString(buffer, 0, buffer.Length));
                    }
                }
            }
        }

以上是SocketsServer类中需添加的私的变量及修改的StartServer方法

  private System.Threading.Thread _listenningthread;
 
        public void StartServer(int port)
        {
            TcpListener listener = new TcpListener(IPAddress.Any, port);
            listener.Start();
            SocketsServer server = new SocketsServer(listener);
            _serverListenThread = new System.Threading.Thread(new System.Threading.ThreadStart(server.Start));
            _listenningthread = new System.Threading.Thread(new System.Threading.ThreadStart(server.Listenning));
            _serverListenThread.Start();
            _listenningthread.Start();
        }

以上是SocketsFactory类中需添加的代码 

    13、在SocketsFactory类中加入StartListen方法,并在TestForm_Load事件中加入如下代码:

SocketsFactory.SendMessage("Hello World!", _connection);

    14、再运行服务端与客户端。即可看到如下结果: 

结果测试中的断点输出结果

14、当我们看到输出窗口中出现了Hello World!时,表明通信成功。(下载源代码

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值