1. 程式人生 > 實用技巧 >JAVA套接字實現簡易的雙人通訊系統

JAVA套接字實現簡易的雙人通訊系統

JAVA套接字實現簡易的雙人通訊系統

JAVA套接字資料

socket是基於應用服務與TCP/IP通訊之間的一個抽象,他將TCP/IP協議裡面複雜的通訊邏輯進行分裝,對使用者來說,只要通過一組簡單的API就可以實現網路的連線。借用網路上一組socket通訊圖給大家進行詳細講解:

首先,服務端初始化ServerSocket,然後對指定的埠進行繫結,接著對埠及進行監聽,通過呼叫accept方法阻塞,此時,如果客戶端有一個socket連線到服務端,那麼服務端通過監聽和accept方法可以與客戶端進行連線。

以上資料:

作者:長道
連結:https://www.jianshu.com/p/cde27461c226


來源:簡書

解決方案

綜上所述,JAVA套接字需要一個SeverSocket物件作為服務端,監聽Socket的連線請求,需要一個Socket物件作為客戶端,向SeverSocket傳送連線的請求。客戶端和服務端建立連線後為全雙工,兩端均可接收和傳送資料,接收和傳送均可用流來實現。但是若兩端僅僅用while迴圈來不停的傳送和接受資料會發生阻塞,也就是說只有一端完成傳送操作後,才能開始接受操作,而鍵盤讀取字串的函式是阻塞的,sock流的讀寫也會發生阻塞,只有輸入並按下回車才會繼續執行,另一端也相同。最終造成的結果是兩端分別每次只能說一句話,只有對方發來資訊後,才可也說下一句。解決方法就是利用多執行緒,服務端和客戶端都設定兩個執行緒,一個執行緒專門用來接受資訊,一個專門用來發送資訊。這樣,接收和傳送互不影響,消除阻塞。

主要程式碼塊

服務端,接收客戶端的連線請求,建立新的執行緒:

客戶端,請求連線,並建立新的執行緒:

接收的執行緒:不斷從輸入流讀取資料並列印

傳送的執行緒:不斷從鍵盤讀取字串並寫入輸出流

客戶端和服務端的接收和傳送程序基本相同

執行結果

最終程式碼

服務端

package com;

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

public class Server{
	static ServerSocket serverSocket;
	public static void main(String[] args) {
		try {
			serverSocket = new ServerSocket(1515);
			while(true) {
				Socket accept_client = serverSocket.accept(); 
				new Thread(new ServerIn(accept_client)).start();
				new Thread(new ServerOut(accept_client)).start();
			}
		} catch (IOException e) {
			e.printStackTrace();
			try {
				serverSocket.close();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}
}
//接受的執行緒
class ServerIn implements Runnable{
	Socket socket;
	
	ServerIn(Socket socket){
		this.socket = socket;
	}
	@Override
	public void run() {
		try {
			InputStream in = socket.getInputStream();
			while(true) {
				byte infile[] = new byte[1024];
				int size  = in.read(infile);
				String string = new String(infile,0,size);
				if(!string.equals("") && !string.equals("\n")) System.out.println("message from client: "+ string);
			}
		} catch (IOException e) {
			e.printStackTrace();
			try {
				socket.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
	}
}
//傳送的執行緒
class ServerOut implements Runnable{
	Socket socket;
	Scanner reader = new Scanner(System.in);
	ServerOut(Socket socket){
		this.socket = socket;
	}
	public void run() {
		try {
			OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream());
			while(true) {
				String string  = reader.nextLine();
				out.write(string);
				out.flush();
			}
		} catch (IOException e) {
			e.printStackTrace();
			try {
				socket.close();
				reader.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
	}	
}

客戶端

package com;

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

public class Client{
	public static void main(String[] args) {
		try {
			Socket client = new Socket("127.0.0.1",1515);
			new Thread(new ClientIn(client)).start();
			new Thread(new ClientOut(client)).start();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
//接受的執行緒
class ClientIn implements Runnable{
	Socket socket;
	ClientIn(Socket socket){
		this.socket = socket;
	}
	@Override
	public void run() {
		try {
			InputStream in = socket.getInputStream();
			while(true) {
				byte infile[] = new byte[1024];
				int size = in.read(infile);
				String string = new String(infile,0,size);
				if(!string.equals("") && !string.equals("\n")) System.out.println("message from server: "+ string);
			}
		} catch (IOException e) {
			e.printStackTrace();
			try {
				socket.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
	}
	
}
//傳送的執行緒
class ClientOut implements Runnable{
	Socket socket;
	Scanner reader = new Scanner(System.in);
	ClientOut(Socket socket){
		this.socket = socket;
	}
	public void run() {
		try {
			OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream());
			while(true) {
				String string  = reader.nextLine();
				out.write(string);
				out.flush();
			}
		} catch (IOException e) {
			e.printStackTrace();
			try {
				socket.close();
				reader.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
	}
}

計算1913 李文軒