基於Java Socket編程的人工智障1.0

本文地址:https://heyzen.club/index.php/J/118.html
個人博客地址:https://heyzen.club/

近期,看到硬盤中存放的Java視頻中有一個Java Socket編程。對,我沒有打開之前不知道是關於什麼的。一直以爲Socket是鎖(lock)。
這週末,也就是昨天和今天,對Java Socket編程有了一個初步的理解。

首先Socket,套接字,插座,就像他的翻譯“插座”一樣。是一種計算機與計算機溝通的樞紐。
Socket分爲流式(SOCK_STREAM)套接字(面向連接,對應TCP協議),原始式套接字(SOCK_RAM)和包式套接字(這個名字暫且這樣叫吧 對應網絡傳輸的UDP協議)

思考
如何建立兩個節點之間的網絡連接?
如何向另外一個節點電腦發送信息?
如何從外部節點接受一個請求並給予響應?
如何應用網絡協議編程?

連接請求
接受請求
連接成功
發送信息
接收信息
關閉連接

在Java中在java.net這個包中。
現在的網絡編程架構一般爲 B/S架構。

TCP協議,數據可靠傳遞。
UDP協議:數據不可靠傳輸,代價小,效率高,數據安全性不高
流式套接字

服務器端處理順序
(1)建立一個服務器Socket綁定指定端口並開始監聽
(2)使用accept()方法阻塞等待監聽,獲得新的連接
(3)建立輸入輸出流
(4)在已有的協議上產生會話
(5)使用close()關閉流和Socket

客戶端處理順序
(1) 建立客戶端Socket連接,指定服務器的位置以及端口
(2) 得到Socket的讀寫流
(3) 利用流按照一定的協議對Socket進行讀/寫操作
(4) 使用close()關閉流和Socket

傳輸的時候,可以傳入字符串,也可以傳入對象(傳對象的時候需要實現序列化),但是使用的是不同的流。關於流,這是我近期要補的知識了。因爲之前學的時候沒有聽這一部分。

此時服務器是單用戶機制,而一般服務器肯定是多用戶訪問的,所以此時可以使用多線程。
服務器一直監聽
一個socket對應一個線程

如何在服務器獲得每個客戶端的IP地址
(1)InetAdress類:表示互聯網協議地址,包含IP地址。是Java對IP地址的封裝。

服務器端代碼

package server;

import java.io.*;
import java.net.Socket;

/**
 * @author Zen
 * @version $Id: ServerThread.java, v 0.1 2018/12/22 3:51 Zen Exp $
 */
public class ServerThread extends Thread{
    //和本線程相關的Socket
    Socket socket = null;
    public ServerThread(Socket socket){
        this.socket = socket;
    }

    //線程啓動
    public void run(){
        try {
            /*//1.建立一個服務器Socket綁定端口,並指定1219端口監聽
            ServerSocket serverSocket = new ServerSocket(8800);
            //2.使用accept()方法阻塞等待監聽,獲得新的連接
            Socket socket = serverSocket.accept();*/
            //3.獲得輸入流
            //4.讀取用戶輸入信息
            InputStream inputStream = socket.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            OutputStream outputStream = socket.getOutputStream();
            PrintWriter printWriter = new PrintWriter(outputStream);
            String info = null;
            String reply = null;
            while (!((info = bufferedReader.readLine()) == null)) {
                reply = info;
                System.out.println("收到客戶端請求信息:" + info);
            }
            reply = reply.replace("嗎", "");
            reply = reply.replace("?", "!");
            reply = reply.replace("?", "!");
            printWriter.write(reply);
            printWriter.close();
            outputStream.close();
            bufferedReader.close();
            inputStream.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

客戶端代碼

package client;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

/**
 * @author Zen
 * @version $Id: AIChatClient.java, v 0.1 2018/12/22 2:30 Zen Exp $
 */
public class AIChatClient {
    public static void main(String[] args) {

            try {
                //(1) 建立客戶端Socket連接,指定服務器的位置以及端口
                boolean flag=true;
                while(flag) {
                Socket socket = new Socket("localhost", 8800);
                //(2) 得到Socket的讀寫流

                    OutputStream outputStream = socket.getOutputStream();
                    PrintWriter printWriter = new PrintWriter(outputStream);
                    //輸入流
                    InputStream inputStream = socket.getInputStream();
                    BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
                    //(3) 利用流按照一定的協議對Socket進行讀/寫操作
                    Scanner scanner = new Scanner(System.in);
                    String info = scanner.next();
                    if(info.equals("quit")){
                        System.out.println("系統正在退出...");
                        Thread.sleep(500);
                        System.out.println("系統退出成功");
                        break;
                    }
                   /* System.out.println("客戶端:" + info);*/
                    printWriter.write(info);
                    printWriter.flush();
                    socket.shutdownOutput();
                    //接受服務器的響應並且打印顯示
                    String reply;
                    while (!((reply = br.readLine()) == null)) {
                        System.out.println("智障1.0:" + reply);
                    }
                    //關閉資源
                    br.close();
                    inputStream.close();
                    printWriter.close();
                    socket.close();
                }
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }

    }
}

多線程

/**
 * eigpay.com Inc.
 * Copyright (c) 2013-2018 All Rights Reserved.
 */
package Thread;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author Zen
 * @version $Id: ServerThread.java, v 0.1 2018/12/22 3:51 Zen Exp $
 */
public class ServerThread extends Thread{
    //和本線程相關的Socket
    Socket socket = null;
    public ServerThread(Socket socket){
        this.socket = socket;
    }

    //線程啓動
    public void run(){
        try {
            /*//1.建立一個服務器Socket綁定端口,並指定1219端口監聽
            ServerSocket serverSocket = new ServerSocket(8800);
            //2.使用accept()方法阻塞等待監聽,獲得新的連接
            Socket socket = serverSocket.accept();*/
            //3.獲得輸入流
            //4.讀取用戶輸入信息
            InputStream inputStream = socket.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            OutputStream outputStream = socket.getOutputStream();
            PrintWriter printWriter = new PrintWriter(outputStream);
            String info = null;
            String reply = null;
            while (!((info = bufferedReader.readLine()) == null)) {
                reply = info;
                System.out.println("收到客戶端請求信息:" + info);
            }
            reply = reply.replace("嗎", "");
            reply = reply.replace("?", "!");
            reply = reply.replace("?", "!");
            printWriter.write(reply);
            printWriter.close();
            outputStream.close();
            bufferedReader.close();
            inputStream.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

基於UDP協議,就沒寫人工智障了,只是做了一個小Demo。

DatagramPacket 數據包。封裝二零數據的長度,目標地址和目標端口。
DatagramSocket 發送和接受數據包的套接字

構造方法

客戶端 服務器端
1.創建接受方服務器套接字,並綁定端口號
2.確定數據包接受的數據的數組大小
3.創建接受類型的數據包,數據將存儲在數組中
4.通過套接字接受數據
5.及解析發送方發送的數據
6.釋放資源

客戶端
1.確定發送給服務器的信息,服務器地址以及端口
2.創建數據包,發送指定長度的信息到指定服務器的指定端口
3.創建DatagramSocket對象
4.向服務器發送數據包
5.釋放資源

URL URLConnection

用戶登錄
多用戶登錄
持續請求

基於UDP協議
無連接
投出數據包
數據安全性不佳

java.net
DatagramPacket 數據包封裝了數據、數據長度、
DatagramSocket 不維護連接狀態 也不產生輸出輸出流

服務器端代碼

package UDP;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;
import java.net.SocketException;

/**
 * @author Zen
 * @version $Id: AIChatServer.java, v 0.1 2018/12/22 15:46 Zen Exp $
 */
public class AIChatServer {
    public static void main(String[] args) {
        try {
            //1.創建接受方套接字。並指定端口號
            DatagramSocket datagramSocket = new DatagramSocket(8800);
            //2.確定數據包接受的數據的數組大小
            byte[] buf=new byte[1024];
            //3.創建接受類型的數據包,數據將存儲在數組中
            DatagramPacket datagramPacket = new DatagramPacket(buf,buf.length);
            //4.通過套接字接受數據
            datagramSocket.receive(datagramPacket);
            //5.解析發送方發送的數據
            String message = new String(buf,0,buf.length);
            System.out.println(message);
            //響應
            String reply = "您好,在的。";
            byte [] replys = reply.getBytes();
            SocketAddress socketAddress = datagramPacket.getSocketAddress();
            DatagramPacket dp2 = new DatagramPacket(replys,replys.length,socketAddress);
            datagramSocket.send(dp2);
            //6.釋放資源
            datagramSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客戶端代碼

/**
 * eigpay.com Inc.
 * Copyright (c) 2013-2018 All Rights Reserved.
 */
package UDP;

import java.io.IOException;
import java.net.*;

/**
 * @author Zen
 * @version $Id: AIChatClient.java, v 0.1 2018/12/22 15:47 Zen Exp $
 */
public class AIChatClient {
    public static void main(String[] args) {
        //確定發送給服務器的信息,服務器地址以及端口
        String mess = "你好,我想諮詢一個問題";
        byte[] buf = mess.getBytes();
        InetAddress inetAddress =null;
        try {
            inetAddress=InetAddress.getByName("localhost");
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        int port = 8800;
        //創建數據包,發送指定長度的信息到指定服務器的指定端口
        DatagramPacket datagramPacket = new DatagramPacket(buf,buf.length,inetAddress,port);
        //創建DatagramSocket對象
        DatagramSocket datagramSocket = null;
        try {
            datagramSocket = new DatagramSocket();
        } catch (SocketException e) {
            e.printStackTrace();
        }
        //向服務器發送數據包
        try {
            datagramSocket.send(datagramPacket);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //接收服務器響應
        byte[] buf2 = new byte[1024];
        DatagramPacket dp2 = new DatagramPacket(buf2,buf2.length);
        try {
            datagramSocket.receive(dp2);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String reply = new String(buf2,0,buf2.length);
        System.out.println(reply);
    }
}

先總結一下就這樣吧,之後寫一篇文章,標題就叫做。我一個人利用AI核心開源代碼,結合Java Socket編程,寫了一個人工智能機器人。

https://heyzen.club/index.php/J/118.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章