Swoole 网络通信协议,固定江门。

网络通讯进程中,恐怕会现出分包和合包的情形。具体意况如https://wiki.swoole.com/wiki/page/484.html文档所讲的。这里测试了下固定包头的协议。示例代码如下

互联网通讯,互连网通讯协议

 

1.解包封装的章程 

一 概述

communicationPack.php

<?php
//对数据信息封装
function packData($sendData,$packModel){
    return pack($packModel, strlen($sendData)).$sendData;
}

//解包
function unpackData($rcvData,$packModel){
    $length = $packModel=='N'?4:2;
    return substr($rcvData,$length);
}

1.互连网模型

OSI(Open System
Interconnection,开放式系统互联)模型,是对互连网系统结构的不外乎,将网络分为七层:应用层、表示层、会话层、传输层、互联网层、数据链路层、物理层。

2.服务端 tcpServer.php

2.IP协议

网络层协议,规定了在互连网上规定与寻找统计机的条条框框。

<?php
require_once 'communicationPack.php';
$packModel = 'N';
//创建Server对象,监听 127.0.0.1:9501端口
$serv = new swoole_server("127.0.0.1", 9501);
$serv->set(array(
    'open_length_check' => true,
    'package_max_length' => 2000000,
    'package_length_type' => $packModel, //see php pack()
    'package_length_offset' => 0,
    'package_body_offset' => $packModel=='N'?4:2,
));
//监听连接进入事件
$serv->on('connect', function ($serv, $fd) {
    echo "Client: Connect.\n";
});

//监听数据接收事件
$serv->on('receive', function ($serv, $fd, $from_id, $data) use($packModel){
    echo "#{$serv->worker_id}>> received length=" . strlen($data) ."data=".$data. "}\n";
    $data = unpackData($data,$packModel);
    $returnStr = "Server: ".$data;
    $serv->send($fd, packData($returnStr,$packModel));
});

//监听连接关闭事件
$serv->on('close', function ($serv, $fd) {
    echo "Client: Close.\n";
});

//启动服务器
$serv->start();

3.TCP协议

传输层的一种多少传输协议,数据传输前经过“几遍握手”建立连接,然后再发送数据,适用于对数据准确性须要较高的动静,由于数量传输前要求树立连接,传输速度较慢。

启航服务端

4.UDP协议

传输层的一种多少传输协议,数据传输前不必要树立连接,适用于对数据准确性须求不高的状态,传输数据较快,一般聊天音信都因而该协议传输。

图片 1

5.HTTP协议

HTTP协议属于应用层协议,为操作系统或互联网应用程序提供访问网络服务的接口。

 

6.端口port

当数码到达计算机后,为了找到对象应用程序,为每一个应用程序分配了3个整数值,取值0-65535,那么些整数值就是端口,从中可以见到,端口代表了微机上一个应用程序,保险数据准确到达预订的先后。2个端口不可以而且被多个应用程序占用,2个应用程序甘休之后,端口不会即时释放,有贰个内存延迟占有的时刻,这些小时一般十分短。端口、0-1023业已被系统应用程序及其它应用程序占用,程序设计时避免采用那些范围的端口。

3 客户端 tcpClient.php

7.套接字Socket

套接字是数据发送与接收的工具。发送者通过套接字发送数据,接受者通过套接字监听钦命的端口获取数据。

8.无论接纳TCP协议,依旧UDP探究,数据都只能以字节格局发送。

<?php
require_once 'communicationPack.php';
$packModel = 'N';
$client = new swoole_client(SWOOLE_SOCK_TCP);
$client->set(array(
    'open_length_check'     => true,
    'package_length_type'   => $packModel,
    'package_length_offset' => 0,       //第N个字节是包长度的值
    'package_body_offset'   => $packModel=='N'?4:2,       //第几个字节开始计算长度
    'package_max_length'    => 2000000,  //协议最大长度
));
//连接到服务器
if (!$client->connect('127.0.0.1', 9501, 0.5))
{
    die("connect failed.");
}
//向服务器发送数据
//数据协议
$sendData = "test123";
$sendData = packData($sendData,$packModel);
if (!$client->send($sendData))
{
    die("send failed.");
}
//从服务器接收数据
$data = $client->recv();
if (!$data)
{

    die("recv failed.");
}
echo unpackData($data,$packModel);
//关闭连接
$client->close();

二 TCP程序设计

1.停歇通过Socket获取的输入流可能输出流将关闭Socket。

2.因而Socket获取的出口流输出了结后必须关闭,不然另一端对应的输入流将阻塞。由于通过输出流对象关闭输出流时,同时关闭Socket对象,将造成另一端不可以取得相应Socket的目的,由此只好通过Socket下的格局shutdownOutput关闭输出流。

 然后开行客户端

3.客户端的相似步骤: 

Socket socket=new Socket(String host,int port);//创建客户端Socket,发送与接收数据,需要指明服务器IP与端口
OutputStream os=socket.getOutputStream();//获取输出流,向服务器发送数据
..........
os.flush();
socket.shutdownOutput();//关闭输出流,防止服务器端阻塞

InputStream is=socket.getInputStream();//获取输入流,输入流包含服务器的反馈信息
............

socket.close();//关闭socket,同时关闭输入与输出流

图片 2

4.服务器的貌似步骤:

ServerSocket server=new ServerSocket(int port);//建立服务器端套接字,指定监听端口
Socket socket=server.accept();//获取访问客户端的Socket,阻塞线程
InputStream is=socket.getInputStream();//获取输入流,其中包含客户端发送的数据
.............

OutputStream os=socket.getOutputStream();//获取输出流,向客户端反馈信息
..............
os.flush();
os.shutdownOutput();

server.close();

劳动端会打印

5.Demo

图片 3

客户端

package com.javase.networkCommunication.tcp.demo02;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class ImgClient {

    public static void main(String[] args) throws UnknownHostException, IOException {
        Socket socket = new Socket("192.168.146.1", 10007);
        FileInputStream is = new FileInputStream("Files/1.jpg");
        OutputStream os = socket.getOutputStream();
        byte[] buf = new byte[1024];// 先将数据读取到缓冲区,比频繁的从硬盘读取速度快
        int length = 0;
        while ((length = is.read(buf)) != -1) {
            os.write(buf, 0, length);
        }
        os.flush();
        socket.shutdownOutput();// 如果输出流不关闭,服务端对应的输入流会阻塞

        InputStream replyIs = socket.getInputStream();//不会阻塞线程
        byte[] buf01 = new byte[1024];
        int length01 = replyIs.read(buf01);
        String reply = new String(buf01, 0, length01);
        System.out.println(reply);

        is.close();
        socket.close();
    }

}

pack N是将数据转成了无符号30位的数字,这么些刚好长度是六个字节,所以设定

服务器

package com.javase.networkCommunication.tcp.demo02;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

import org.junit.Test;

public class ImgServer {

    @Test
    public void test01() throws IOException {
        ServerSocket serverSocket = new ServerSocket(10007);
        Socket socket = serverSocket.accept();// 线程阻塞,等待请求
        System.out.println("hostAddress=" + socket.getInetAddress().getHostAddress());
        InputStream is = socket.getInputStream();
        FileOutputStream os = new FileOutputStream("Files/2.jpg");
        System.out.println(1);
        byte[] buf = new byte[1024];
        int length = 0;
        System.out.println(2);
        int count = 3;
        while ((length = is.read(buf)) != -1) {
            os.write(buf, 0, length);
            System.out.println(count++);
        }
        os.flush();
        os.close();
        System.out.println("图片上传结束");

        /*PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
        out.write("success");*/
        OutputStream out = socket.getOutputStream();
        out.write("success".getBytes());
        out.flush();
        socket.shutdownOutput();
        System.out.println("响应数据已发出");

        serverSocket.close();
    }

}
package_body_offset=4

三 UDP程序设计

 

1.数码处理方式

UDP商谈以数据包的花样发送数据,每种包的最大值64k。

2.发送数据的形似步骤:

DatagramSocket socket=new DatagramSocket();//创建数据报套接字用于发送数据
//DUP协议采用数据包分段发送数据,因此需要建立数据包,在数据包中指明目的地IP与端口
DatagramPacket packet= DatagramPacket(byte buf[], int offset, int length,InetAddress address, int port);
socket.send(packet);

3.接收数据的一般步骤:

DatagramSocket socket=new DatagramSocket(int port);//创建监听指定端口的数据报套接字
DatagramPacket packet=new DatagramPacket(byte buf[], int length);
socket.receive(packet);

http://www.bkjia.com/Javabc/1216566.htmlwww.bkjia.comtruehttp://www.bkjia.com/Javabc/1216566.htmlTechArticle网络通信,网络通信协议 一 概述 1.互连网模型
OSI(Open System
Interconnection,开放式系统互联)模型,是对网络系统结构的席卷,将网络分为七层…

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图