JAVA Sokcet(服务端)连接WebSocket个人总结

JAVA Socket连接WebSocket个人总结

如果大家是Web项目的话就可以不用JAVA的Socket去进行连接客户端的WebSocket。因为javaee-api-7.0以上版本有对服务器端的WebSocket进行封装,通过启动服务就可以让网页轻松访问到连接。
我这里是用Java中的java.net.socket与之连接,这是一个比较复杂的服务器端,需要我们自己去封装一些与浏览器之间的操作。握手操作是建立连接的桥梁,然后建立起TCP通信,即可。
下面直接上代码吧
private int port = 8888;
serverSocket = new ServerSocket(port);
System.out.println("服务器启动");

定义端口,创建ServerSocket对象,这时服务就启动了。服务启动了,我们就要来接收客户端那边对我们的响应了。
socket = serverSocket.accept();
//开启线程,接收不同的socket请求
Thread workThread = new Thread(new Handler(socket));
workThread.start();
我们同构accept()来接收响应,如果接收成功那么我们创建一个新的线程去操作它的具体内容。
//获取socket输入流信息
InputStream in = socket.getInputStream();
byte[] buf = new byte[1024];
//读到字节(读取输入流数据到缓存)
int len = in.read(buf, 0, 1024);
                //读到字节数组(定义一个容纳数据大小合适缓存区)
                byte[] res = new byte[len];
                //将buf内中数据拷贝到res中
                System.arraycopy(buf, 0, res, 0, len);
                //打印res缓存内容
                String key = new String(res);
                if(!hasHandshake && key.indexOf("Key") > 0){
                    //握手
//通过字符串截取获取key值
                    key = key.substring(0, key.indexOf("==") + 2);
                    key = key.substring(key.indexOf("Key") + 4, key.length()).trim();
                    //拼接WEBSOCKET传输协议的安全校验字符串
                    key+= "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
                    //通过SHA-1算法进行更新
                    MessageDigest md = MessageDigest.getInstance("SHA-1");  
                    md.update(key.getBytes("utf-8"), 0, key.length());
                    byte[] sha1Hash = md.digest();  
                    //进行Base64加密
                    sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();  
                    key = encoder.encode(sha1Hash);  
                    //服务器端返回输出内容
                    pw.println("HTTP/1.1 101 Switching Protocols");
                    pw.println("Upgrade: websocket");
                    pw.println("Connection: Upgrade");
                    pw.println("Sec-WebSocket-Accept: " + key);
                    pw.println();
                    pw.flush();
//将握手标志更新,只握一次
                    hasHandshake = true;
                    //服务器返回成功,---握手协议完成,进行TCP通信
 
这样就可以进行正常的交互了!
 
贴上源码:
package com.cx;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JTextArea;
/**
  * @author(作者) :Cx
 */
public class WebServer {
	private int port = 8888;
    private ServerSocket serverSocket;
    private List<Handler> handlers = new ArrayList<Handler>();
    JTextArea text;//显示信息
 
    public WebServer(JTextArea text) throws IOException {
    	this.text = text;
        serverSocket = new ServerSocket(port);
        text.setText("WebSocket服务器已启动!\n");
        text.append("等待客户端连接...!\n");
    }
 
    public void service() {
        Socket socket = null;
        while (true) {
            try {
            	//接收socket请求
                socket = serverSocket.accept();
                //判断
                if(handlers.size()>0){
            		for (Handler handler : handlers) {
            			if(handler.getSpeech()!=null){
            				handler.getSpeech().flag=false;
            			}
					}
            		handlers.clear();
            	}
                //开启线程,接收不同的socket请求
                Handler handler = new Handler(socket);
                handlers.add(handler);
                Thread workThread = new Thread(handler);
                workThread.start();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
 
    class Handler implements Runnable {
    	private Speech speech = new Speech();
        private Socket socket;
        private boolean hasHandshake = false;
        Charset charset = Charset.forName("UTF-8");  
        
        public Speech getSpeech(){
        	return this.speech;
        }
        
        public Handler(Socket socket) {
            this.socket = socket;
        }
 
        private PrintWriter getWriter(Socket socket) throws IOException {
            OutputStream socketOut = socket.getOutputStream();
            return new PrintWriter(socketOut, true);
        }
        public void run() {
            try {
                System.out.println("New connection accepted"
                        + socket.getInetAddress() + ":" + socket.getPort());
                text.append("New connection accepted!.."+socket.getInetAddress()+":"+socket.getPort()+"\n");
                text.setCaretPosition(text.getText().length());
                //获取socket输入流信息
                InputStream in = socket.getInputStream();
                //获取socket输出
                PrintWriter pw = getWriter(socket);
                //读入缓存(定义一个1M的缓存区)
                byte[] buf = new byte[1024];
                //读到字节(读取输入流数据到缓存)
                int len = in.read(buf, 0, 1024);
                //读到字节数组(定义一个容纳数据大小合适缓存区)
                byte[] res = new byte[len];
                //将buf内中数据拷贝到res中
                System.arraycopy(buf, 0, res, 0, len);
                //打印res缓存内容
                String key = new String(res);
                if(!hasHandshake && key.indexOf("Key") > 0){
                    //握手
                	//通过字符串截取获取key值
                    key = key.substring(0, key.indexOf("==") + 2);
                    key = key.substring(key.indexOf("Key") + 4, key.length()).trim();
                    //拼接WEBSOCKET传输协议的安全校验字符串
                    key+= "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
                    //通过SHA-1算法进行更新
                    MessageDigest md = MessageDigest.getInstance("SHA-1");  
                    md.update(key.getBytes("utf-8"), 0, key.length());
                    byte[] sha1Hash = md.digest();  
                    //进行Base64加密
                    sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();  
                    key = encoder.encode(sha1Hash);  
                    //服务器端返回输出内容
                    pw.println("HTTP/1.1 101 Switching Protocols");
                    pw.println("Upgrade: websocket");
                    pw.println("Connection: Upgrade");
                    pw.println("Sec-WebSocket-Accept: " + key);
                    pw.println();
                    pw.flush();
                    //将握手标志更新,只握一次
                    hasHandshake = true;
                    //服务器返回成功,---握手协议完成,进行TCP通信
                    //进行语音交互
					//当时做语音时用到的
                    speech.verifySocket(this);
                    //----------------------以下是获取到浏览器发送的消息--------
                    //接收数据
                    byte[] first = new byte[1];
                	//这里会阻塞
                    int read = in.read(first, 0, 1);
                    //读取第一个字节是否有值,开始接收数据
                    while(read > 0){
                    	//让byte和十六进制做与运算(二进制也就是11111111)
                    	//获取到第一个字节的数值
                        int b = first[0] & 0xFF;
                        //1为字符数据,8为关闭socket(只要低四位的值判断)
                        byte opCode = (byte) (b & 0x0F);
                        if(opCode == 8){
                            socket.getOutputStream().close();
                            break;
                        }
                        b = in.read();
                        //只能描述127
                        int payloadLength = b & 0x7F;
                        if (payloadLength == 126) {
                            byte[] extended = new byte[2];
                            in.read(extended, 0, 2);
                            int shift = 0;
                            payloadLength = 0;
                            for (int i = extended.length - 1; i >= 0; i--) {
                                payloadLength = payloadLength + ((extended[i] & 0xFF) << shift);
                                shift += 2;
                            }
                        } else if (payloadLength == 127) {
                            byte[] extended = new byte[8];
                            in.read(extended, 0, 8);
                            int shift = 0;
                            payloadLength = 0;
                            for (int i = extended.length - 1; i >= 0; i--) {
                                payloadLength = payloadLength + ((extended[i] & 0xFF) << shift);
                                shift += 8;
                            }
                        }
                        //掩码
                        byte[] mask = new byte[4];
                        in.read(mask, 0, 4);
                        int readThisFragment = 1;
                        ByteBuffer byteBuf = ByteBuffer.allocate(payloadLength + 30);
                        byteBuf.put("浏览器: ".getBytes("UTF-8"));
                        while(payloadLength > 0){
                             int masked = in.read();
                             masked = masked ^ (mask[(int) ((readThisFragment - 1) % 4)] & 0xFF);
                             byteBuf.put((byte) masked);
                             payloadLength--;
                             readThisFragment++;
                        }
                        byteBuf.flip();
                        //将内容返回给客户端
                        responseClient(byteBuf, true);
                        //打印内容
                        printRes(byteBuf.array());
                        in.read(first, 0, 1);
                    }
                }
                in.close();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
            	System.out.println("*********************废弃Socket回收阶段******************!");
                try {
                    if (socket != null){
                        socket.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
 
        public void responseClient(ByteBuffer byteBuf, boolean finalFragment) throws IOException {
            OutputStream out = socket.getOutputStream();
            int first = 0x00;
            //是否是输出最后的WebSocket响应片段
                if (finalFragment) {
                    first = first + 0x80;
                    first = first + 0x1;
                }
                out.write(first);
                if (byteBuf.limit() < 126) {
                    out.write(byteBuf.limit());
                } else if (byteBuf.limit() < 65536) {
                out.write(126);
                out.write(byteBuf.limit() >>> 8);
                out.write(byteBuf.limit() & 0xFF);
                } else {
                // Will never be more than 2^31-1
                out.write(127);
                out.write(0);
                out.write(0);
                out.write(0);
                out.write(0);
                out.write(byteBuf.limit() >>> 24);
                out.write(byteBuf.limit() >>> 16);
                out.write(byteBuf.limit() >>> 8);
                out.write(byteBuf.limit() & 0xFF);
                }
                // Write the content
                out.write(byteBuf.array(), 0, byteBuf.limit());
                out.flush();
        }
         
        private void printRes(byte[] array) {
            ByteArrayInputStream  byteIn = new ByteArrayInputStream(array);
            InputStreamReader reader = new InputStreamReader(byteIn, charset.newDecoder());
            int b = 0;
            String res = "";
            try {
                while((b = reader.read()) > 0){
                    res += (char)b;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println(res);
        }
    }
}
package com.cx;

import java.nio.ByteBuffer;

import com.cx.WebServer.Handler;

/**
  * @author(作者) :Cx
 */
public class Speech {
	Boolean flag = true;
	//加上锁,只允许一个网页连接进行交互。
	public synchronized   void verifySocket(Handler handle) throws Exception{
		String rec =null;
		while (flag) {
			   Thread.sleep(10);
			   rec = WebRecorder.recData;
				if(rec !=null){
					synchronized(rec) {
					ByteBuffer byteBuf = ByteBuffer.allocate(30);
					byteBuf.put(rec.getBytes("UTF-8"));
					handle.responseClient(byteBuf, true);
					System.out.println("返回成功"+rec);
					WebRecorder.recData=null;
				}
			}	
		}
	}
}

 
 
 
 
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
你好,以下是一段使用 Java 编写的 WebSocket 服务端代码: ``` import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.util.Iterator; import java.util.Set; public class WebSocketServer { private static final int PORT = 808; private static final Charset CHARSET = Charset.forName("UTF-8"); public static void main(String[] args) throws IOException { ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().bind(new InetSocketAddress(PORT)); serverSocketChannel.configureBlocking(false); Selector selector = Selector.open(); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); while (true) { int readyChannels = selector.select(); if (readyChannels == ) { continue; } Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while (keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); if (key.isAcceptable()) { ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel(); SocketChannel socketChannel = serverChannel.accept(); socketChannel.configureBlocking(false); socketChannel.register(selector, SelectionKey.OP_READ); } else if (key.isReadable()) { SocketChannel socketChannel = (SocketChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocate(1024); int bytesRead = socketChannel.read(buffer); if (bytesRead == -1) { socketChannel.close(); continue; } buffer.flip(); CharBuffer charBuffer = CHARSET.decode(buffer); String message = charBuffer.toString().trim(); System.out.println("Received message: " + message); socketChannel.write(CHARSET.encode("Server received your message: " + message)); } keyIterator.remove(); } } } } ``` 以上代码实现了一个简单的 WebSocket 服务端,监听 808 端口,接收客户端发送的消息并回复。当客户端连接时,服务端会注册一个 OP_ACCEPT 事件,当客户端发送消息时,服务端会注册一个 OP_READ 事件。在 OP_READ 事件中,服务端会读取客户端发送的消息并回复。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值