廖雪峯Java13網絡編程-1Socket編程-3TCP多線程編程

TCP多線程編程
一個ServerSocket能夠和多個客戶端同時創建鏈接,因此一個Server能夠同時與多個客戶端創建好的Socket進行雙向通訊。
所以服務器端,當咱們打開一個Socket之後,一般使用一個無限for循環,在這個for循環內部,每次調用accept方法,返回一個與遠程客戶新建的Socket鏈接,緊接着啓動一個新的線程,來處理這個鏈接。java

ServerSocket ss = new ServerSocket(port);
    for( ; ; ){
        Socket sock = ss.accept();
        Thread t = new Thread(){
            public void run(){
                process(sock);
            }
        }
        t.start();
    }

TCPServer.java編程

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;

public class TCPServer {
    public static void main(String[] args) throws Exception{
        ServerSocket ss = new ServerSocket(9090);
        System.out.println("TCP Server ready");
        for(;;){
            Socket sock = ss.accept();
            System.out.println("Accept from "+sock.getRemoteSocketAddress());
            TimeHandle handle = new TimeHandle(sock);
            handle.start();
        }
    }
}
class TimeHandle extends Thread{
    Socket sock;
    TimeHandle(Socket sock){
        this.sock = sock;
    }
    public void run(){
        try(BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream(), StandardCharsets.UTF_8))){
            try(BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream(),StandardCharsets.UTF_8))){
                for(;;){
                    String cmd = reader.readLine();
                    if("q".equals(cmd)){
                        writer.write("bye!\n");
                        writer.flush();
                        break;
                    }else if("time".equals(cmd)){
                        writer.write(LocalDateTime.now().toString()+"\n");
                        writer.flush();
                    }else{
                        writer.write("Sorry?\n");
                        writer.flush();
                    }
                }
            }
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try{
                this.sock.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

運行2次client,服務器端的運行結果

TCPClient.java服務器

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class TCPClient {
    public static void main(String[] args) throws Exception{
        InetAddress addr = InetAddress.getByName("localhost");
        System.out.println(addr);
        try(Socket sock = new Socket(addr,9090)){
            try(BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream(), StandardCharsets.UTF_8))){
                try(BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream(),StandardCharsets.UTF_8))){
                    writer.write("time\n");
                    writer.flush();
                    String resp = reader.readLine();
                    System.out.println("Response:"+resp);
                    Thread.sleep(1000);
                    writer.write("q\n");
                    writer.flush();
                    resp=reader.readLine();
                    System.out.println("Response:"+resp);
                }
            }
        }
    }
}

總結:

TCP多線程編程模型:多線程

  • 服務器端使用無限循環
  • 每次accept返回後,建立新的線程來處理客戶端請求
  • 每一個客戶端請求對應一個服務線程
  • 使用線程池能夠提升運行效率
相關文章
相關標籤/搜索