美文网首页
Socket简单通信

Socket简单通信

作者: 十月石榴2013 | 来源:发表于2017-12-11 17:22 被阅读21次

    到昨天为止Lis的编写就告一个段落了。回顾这一个月,虽然有所事事,但具体干了什么,学到了什么,直接说出来,还是不容易的。
    最可以独立出来的一个知识点就是socket通信了。
    Socket通信是客户端与服务器之间的通信,客户端在服务器的某个端口找某种服务,如图,用一个不恰当的比喻,就像某个人在琅琊阁的某个书架的锦盒中寻找某种指示。


    image.png
    image.png

    socket可以用于本机内部通信,也可以用于网络。具体的协议我也不清楚,也没有深究。
    编写socket客户端分下列几步。我用的语言是C#,想来所有的语言都差不多是这样的。

    步骤一、openConnestion
    我觉得在这个步骤中比较关键的有。
    绑定服务器IP地址和端口号。(C#:serverSocket.Bind(IPAdress:Port))。
    启动监听。(C#:serverSocket.Listen(n))
    n是设定排队连接请求最多可以有n个,指没连上但等待连接的最多有n个,不是指这个端口能够容纳的连接数只有n个。至于服务器端口最多容纳多少个连接,据说是65535个。

    步骤二、acceptClientSocket
    新建一个线程,非常关键,因为我们循环接收来自端口的客户端连接请求,不新建线程服务器软件就无法进行与socket无关的动作,比如GUI操作。
    不断接收客户端的socket。
    C#:
    While(true)
    {
    ……
    Socket clientSocket = serverSocket.Accept();
    ……
    }
    3.创建接收线程,接收数据。之所以要创建新的接收线程,是因为接收的关键语句receive是阻塞的(至少C#是这样,想来其他的语言都差不多)。

    步骤三、Receive对接收线程的处理
    对接收线程的处理有好几种思路,我使用过两种:A. 每一个客户端就新建一条接收线程;B. 通过IO复用(比如select方法)所有客户端都采用同一条线程监听。
    方法A,关键语句C#:int receiveNumber =myClientSocket.Receive(接收内存缓冲区)。
    这个方法,myClientSocket端口无数据时,则阻塞,有数据则返回数据个数,理论上断开则返回-1,但不知道为啥从来没有真正返回过,每次断开都报异常。
    方法B,关键语句C#:Socket.Select(socket客户端的接收链表, socket客户端的发送链表,socket客户端的异常链表, 允许的阻塞时间),前三个链表可以有两个为null。
    当接收链表中任何一个socket都没有收到数据时,阻塞,收到数据之后即返回,并且参数“socket客户端的接收链表”会改为“接收到数据的socket客户端链表”。因此,再写一个循环语句,循环读取接收到的数据:
    for(int i = 0; i <readList.Count; i++)
    {
    myClientSocket = (Socket)readList[i];
    int receiveNumber =myClientSocket.Receive(接收内存缓冲区);
    ……
    }
    Select语句不是阻塞的,没一个客户端接收区有数据的话会返回socket客户端的接收链表readList.Count=0。但重点是,用了select语句就能节约很多个接收线程,避免时间片轮转到阻塞的Receive语句上,从而使得接收到的数据能更快得到处理。
    还有第三种方法:IOCP(windows)、epoll(linux),略有耳闻,没有用过。

    步骤三、处理接收到的信息。
    视情况而定,没啥好说的。

    步骤四、send发送消息


    image.png

    我使用的是一个客户端对于一个发送线程,平时休眠,发送队列有消息的时候就醒过来发送消息,发完再休眠。

    关键语句C#:myClientSocket.Send(Encoding.ASCII.GetBytes(sendMessage字符串))。

    就这样吧。2017年8月24日。

    相关文章

      网友评论

          本文标题:Socket简单通信

          本文链接:https://www.haomeiwen.com/subject/xgxwixtx.html