请教怎样发送socket请求包,并获得返回数据

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了请教怎样发送socket请求包,并获得返回数据相关的知识,希望对你有一定的参考价值。

这种东西,Google下大把吧,正好前阵子有一个TCP通讯的,借你参考下好了:

Server Side

package nio;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class EchoServer 

    private static int SOCKET_NUM = 55555;

    private static DateFormat dateFormatter = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
    
    /**
     * @param args
     */
    public static void main(String[] args) 
        new EchoServer().start();
    

    public void start() 
        try 
            Selector selector = bindServer();  // 绑定服务端口,并定义一个事件选择器对象记录套接字通道的事件
            
            /* 通过此循环来遍例事件 */
            while (true) 
                log("Waiting events.");
                int n = selector.select(); // 查询事件如果一个事件都没有,这里就会阻塞
                log("Got events: " + n);
                
                ByteBuffer echoBuffer = ByteBuffer.allocate(50); // 定义一个byte缓冲区来存储收发的数据

                /* 循环遍例所有产生的事件 */
                for (SelectionKey key : selector.selectedKeys()) 
                    SocketChannel sc;
                    selector.selectedKeys().remove(key);  // 将本此事件从迭带器中删除
                    
                    /* 如果产生的事件为接受客户端连接(当有客户端连接服务器的时候产生) */
                    if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) 
                        
                        ServerSocketChannel subssc = (ServerSocketChannel) key.channel(); // 定义一个服务器socket通道
                        
                        sc = subssc.accept(); // 将临时socket对象实例化为接收到的客户端的socket
                        
                        sc.configureBlocking(false); // 将客户端的socket设置为异步
                        
                        sc.register(selector, SelectionKey.OP_READ); // 将客户端的socket的读取事件注册到事件选择器中
                       
                        System.out.println("Got new client:" + sc);
                    
                    /* 如果产生的事件为读取数据(当已连接的客户端向服务器发送数据的时候产生) */
                    else if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) 
                        
                        sc = (SocketChannel) key.channel(); // 临时socket对象实例化为产生本事件的socket
                        
                        ByteArrayOutputStream bos = new ByteArrayOutputStream(); // 定义一个用于存储byte数据的流对象,存储全部信息
                        
                        echoBuffer.clear(); // 先将客户端的数据清空
                        
                        try 
                            // 循环读取所有客户端数据到byte缓冲区中,当有数据的时候read函数返回数据长度
                            // NIO会自动的将缓冲区一次容纳不下的自动分段
                            int readInt = 0; // 为读取到数据的长度
                            while ((readInt = sc.read(echoBuffer)) > 0) 
                                // 如果获得数据长度比缓冲区大小小的话
                                if (readInt < echoBuffer.capacity()) 
                                    
                                    byte[] readByte = new byte[readInt]; // 建立一个临时byte数组,将齐长度设为获取的数据的长度
                                    // 循环向此临时数组中添加数据
                                    for (int i = 0; i < readInt; i++) 
                                        readByte[i] = echoBuffer.get(i);
                                    
                                    
                                    bos.write(readByte); // 将此数据存入byte流中
                                
                                // 否则就是获得数据长度等于缓冲区大小
                                else                                     
                                    bos.write(echoBuffer.array()); // 将读取到的数据写入到byte流对象中
                                
                            
                            // 当循环结束时byte流中已经存储了客户端发送的所有byte数据
                            log("Recive msg: " + new String(bos.toByteArray()));
                         catch (Exception e) 
                            
                            e.printStackTrace(); // 当客户端在读取数据操作执行之前断开连接会产生异常信息
                            
                            key.cancel(); // 将本socket的事件在选择器中删除
                            break;
                        
                        
                        writeBack(sc, bos.toByteArray()); // 向客户端写入收到的数据
                    
                
            
         catch (Exception e) 
            e.printStackTrace();
        
    

    /**
     * 绑定服务端口,初始化整个服务
     * @throws IOException
     */
    private Selector bindServer() throws IOException 
        log("Start binding server socket:" + SOCKET_NUM);
        
        Selector selector = Selector.open(); // 定义一个事件选择器对象记录套接字通道的事件

        ServerSocketChannel ssc = ServerSocketChannel.open(); // 定义一个异步服务器socket对象

        ssc.configureBlocking(false);// 将此socket对象设置为异步

        ServerSocket ss = ssc.socket(); // 定义服务器socket对象-用来指定异步socket的监听端口等信息

        InetSocketAddress address = new InetSocketAddress(SOCKET_NUM); // 定义存放监听端口的对象

        ss.bind(address); // 将服务器与这个端口绑定

        ssc.register(selector, SelectionKey.OP_ACCEPT); // 将异步的服务器socket对象的接受客户端连接事件注册到selector对象内

        log("Binded socket at:" + SOCKET_NUM);
        
        return selector;
    
    
    private boolean writeBack(SocketChannel sc, byte[] b) 
        ByteBuffer echoBuffer = ByteBuffer.allocate(b.length); // 建立这个byte对象的ByteBuffer
        echoBuffer.put(b); // 将数据存入 
        
        echoBuffer.flip(); // 将缓冲区复位以便于进行其他读写操作
        try 
            // 向客户端写入数据,数据为接受到数据
            sc.write(echoBuffer);
         catch (IOException e) 
            e.printStackTrace();
            return false;
        
        System.out.println("Msg echo back: " + new String(echoBuffer.array()));
        return true;
    

    private static void log(Object msg) 
        System.out.println("SERVER [" + dateFormatter.format(new Date()) + "]: " + msg);
    
参考技术A 现有TCP/IP协议栈只提供传输的可靠保证,并不提供应用的事务处理数据的可靠性保证,对于事务可靠性保证需要应用自己完成(可以使用接收确认+重发机制+心跳检测) 参考技术B 这是来自autohotkey官方教程的一段例子,其中FileAppend, `n%Hotstring%, %A_ScriptFullPath% 这句我把后面的A_ScriptFullPath换成我的桌面路径或其他路径却怎么也无法运行出来,来自编译器的消息是 >"C:\Program Files\AutoHotkey\AutoHotkey.exe" /ErrorStdOut "C:\Program Files\AutoHotkey\SciTE\TestSuite.ahk" C:\Program Files\AutoHotkey\SciTE\TestSuite.ahk (19) : ==> This line does not contain a recognized action. Specifically: ???. 编译器认定它是一个无法识别的行为。调试了半天,不知道怎么办,求高手解答 热字符串助手 Andreas Borutta 推荐了下面的脚本, 如果您是深度的热字串用户, 那么它会很有用. 使用 Win+H (或您选择的其他热键), 可以把当前选择的文本转变成热字串. 例如, 如 果您在字处理软件中选择了 "by the way", 按下 Win+H 会提示您输入其缩写 (例如 btw), 然后把新热字串添加到脚本中. 之后会重新载入脚本来激活热字串 #h:: ; Win+H hotkey ; 获取当前选择的文本. 使用剪贴板代替 ; "ControlGet Selected", 是因为它可以工作于更大范围的编辑器 ; (即字处理软件). 保存剪贴板当前的内容 ; 以便在后面恢复. 尽管这里只能处理纯文本, ; 但总比没有好: AutoTrim Off ; 保留剪贴板中任何前导和尾随空白字符. ClipboardOld = %ClipboardAll% Clipboard = ; 必须清空, 才能检测是否有效. Send ^c ClipWait 1 if ErrorLevel ; ClipWait 超时. return ; 替换 CRLF 和/或 LF 为 `n 以便用于 "发送原始模式的" 热字串: ; 对其他任何在原始模式下可能出现

websocket

websocket

webSocket是H5中新增的,与HTTP协议是同级别的,只不过它是有状态的(有持久连接)

HTTP协议:

  前端发送请求,后端得到响应并返回数据,断开连接,之后想要再次发送新的请求,就要再次建立连接通道才能发送请求

webSocket:

  前端发送请求,后端得到响应并返回数据,就保持连接,之后想要再次发送新的请求,就可以使用已经建立起来的通道再次发送请求

socket.io

socket.io是nodejs第三方模块文件,用于统一浏览器发送socket请求的方式

下载:npm install socket.io

使用socket.io

let socket_io = require(\'socket.io’);

socket_io(server);

在地址栏中输入:http://localhost:3000/socket.io/socket.io.js 就能得到一个socket文件

与express搭配使用

socket不能和express搭配使用,想要搭配使用只能将express应用转为http服务

第一步:通过express创建应用程序  let app = express();

第二步:将express应用转为http服务  let server = http.createServer(app);

第三步:通过socket处理http服务  let io = socket(server);

socket 服务

后台搭建

第一步:执行socket.io (以上三步)

第二步:通过变量io监听connection事件(通过on方法),该事件会在前端发送socket请求的时候触发

 

 

 

前端搭建

第一步:通过script标签引入socket.io.js文件

第二步:当引入socket.io.js文件之后,向全局暴露一个io变量 。要执行io方法, 并且要监听connect方法

    当我们执行io方法的时候,就会自动发送一个socket请求。这样后台就可以接收到信息。

前后端通信

前端socket:

on方法监听消息

  第一个参数表示消息名称 第二个参数是执行的函数

emit方法触发消息

  第一个参数是消息名称 从第二个参数开始,是传递的数据

后端socket:

on方法监听消息

  第一个参数表示消息名称 第二个参数是执行的函数,通过回调函数中的参数调用on方法

emit方法触发消息

  第一个参数是消息名称 从第二个参数开始,是传递的数据,通过回调函数中的参数调用emit方法

 

注意:前后端发布和接收的消息名称要一致

以上是关于请教怎样发送socket请求包,并获得返回数据的主要内容,如果未能解决你的问题,请参考以下文章

websocket

用PHP怎么发送HTTP POST 请求。怎么获得返回结果。

终端通过GPRS发送UDP数据到固定IP:端口号,socket recvfrom接收不到数据,但却有返回值,如何解决

请教怎么实现异步发送邮件

网络编程 TCP协议:三次握手,四次回收,反馈机制 socket套接字通信 粘包问题与解决方法

TCP协议与socket套接字