欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

解決Java中socket使用getInputStream()阻塞問題

 更新時(shí)間:2021年12月13日 15:35:03   作者:godelgnis  
這篇文章主要介紹了解決Java中socket使用getInputStream()阻塞問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

socket使用getInputStream()阻塞

今天用socket進(jìn)行編程練習(xí)時(shí),發(fā)現(xiàn)程序到了getInputStream()這里就進(jìn)行不下去了

Socket socket = new Socket("127.0.0.1", 800);
ObjectInputStream reader = new ObjectInputStream(socket.getInputStream());
System.out.println("a");
ObjectOutputStream writer = new ObjectOutputStream(socket.getOutputStream());

就這樣的一個(gè)測(cè)試代碼,a不會(huì)打印出來

后來發(fā)現(xiàn)是getInputStream()會(huì)一直阻塞在那里阻塞

我把兩行代碼調(diào)了一下就好了,還不太清楚原因,先記下來

Socket socket = new Socket("127.0.0.1", 800);
ObjectOutputStream writer = new ObjectOutputStream(socket.getOutputStream());
System.out.println("a");
ObjectInputStream reader = new ObjectInputStream(socket.getInputStream());

用線程解決Socket的getInputStream阻塞

1.背景

在Socket通信中,當(dāng)我們希望傳輸對(duì)象時(shí),往往會(huì)用到輸入/輸出對(duì)象流。

ObjectInputStream in=new ObjectInputStream(socket.getInputStream());
ObjectOutputStream out=new ObjectOutputStream(socket.getOutputStream());

2.問題

當(dāng)程序調(diào)用socket.getInputStream()程序被被卡住。

3.原因

socket.getInputStream()方法會(huì)導(dǎo)致程序阻塞,直到inputStream收到對(duì)方發(fā)過來的報(bào)文消息,程序才會(huì)繼續(xù)往下執(zhí)行。

public ObjectInputStream(InputStream in) throws IOException的官方API顯示:

Creates an ObjectInputStream that reads from the specified InputStream. A serialization stream header is read from the stream and verified. This constructor will block until the corresponding ObjectOutputStream has written and flushed the header. [1]

4.解決辦法

用線程的方式處理輸入流。以下為示例代碼:

//===============客戶端代碼 SocketClient.java=====================

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException; 
 
public class SocketClient {
	private Socket socket;
	private ObjectOutputStream out;
	private ObjectInputStream in;	
	public SocketClient(){
		try {
			socket=new Socket("localhost",8081);
			out=new ObjectOutputStream(socket.getOutputStream());
			ReadThread readThread=new ReadThread();
			readThread.start();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void sendMessage(String msg){
		System.out.println("send message:"+msg);
		try {
			out.writeObject(msg);
			out.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	class ReadThread extends Thread{
		boolean runFlag=true;
		public void run(){
			try {
				in=new ObjectInputStream(socket.getInputStream());
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			while(runFlag){
				if(socket.isClosed()){
					return;
				}
				try {
					Object obj=in.readObject();
					if(obj instanceof String){
						System.out.println("Client recive:"+obj);
					}
				} 
				catch (IOException e) {
					e.printStackTrace();
				} 
				catch (ClassNotFoundException e) {
					e.printStackTrace();
				}
			}
		}
		
		public void exit(){
			runFlag=false;
		}
	}
	
	public static void main(String[] args) {
		SocketClient socketClient=new SocketClient();
		System.out.println("build socketClient");
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		socketClient.sendMessage("Hello first.");
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		socketClient.sendMessage("Hello second.");
	} 
}

//============服務(wù)器端代碼 SocketService.java===========

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Date;
 
public class SocketService {
	ServerSocket serverSocket;	
	public SocketService(){
		try {
			serverSocket=new ServerSocket(8081);
			while(true){
				Socket socket=serverSocket.accept();
				SocketServiceThread sst=new SocketServiceThread(socket);
				sst.start();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	class SocketServiceThread extends Thread{
		Socket socket;
		ObjectInputStream in;
		ObjectOutputStream out;
		boolean runFlag=true;
		public SocketServiceThread(Socket socket){
			if(null==socket){
				runFlag=false;
				return;
			}
			this.socket=socket;
			try {
				out=new ObjectOutputStream(socket.getOutputStream());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		public void run(){
			if(null==socket){
				System.out.println("socket is null");
				return;
			}
			try {
				in=new ObjectInputStream(socket.getInputStream());
				while(runFlag){
					if(socket.isClosed()){
						System.out.println("socket is closed");
						return;
					}
					try {
						String obj=(String)in.readObject();
						if(obj instanceof String){
							System.out.println("Server recive:"+obj);
							Date date=new Date();
							out.writeObject("["+date+"]"+obj);
							out.flush();
						}
						else{
							System.out.println("Server recive:"+obj);
						}
					} 
					catch (ClassNotFoundException e) {
						e.printStackTrace();
					}
					catch (SocketException e){
						e.printStackTrace();
						return;
					}
					catch (IOException e){
						e.printStackTrace();
					}
				}
			} catch (IOException e1) {
				e1.printStackTrace();
				return;
			} catch (Exception e){
				return;
			}
		}
		
		public void exit(){
			runFlag=false;
		}
	}
	
	public static void main(String[] args) {
		System.out.println("===============start service===============");
		new SocketService();
	} 
}

5.Socket通信注意事項(xiàng)

(1).writeXXX()方法后一般用flush()來把緩存內(nèi)容發(fā)送出去。

(2).發(fā)送對(duì)象時(shí),對(duì)象必須串行化,即該對(duì)象需要實(shí)現(xiàn)Serializable接口。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 關(guān)于maven本地倉庫的配置方式

    關(guān)于maven本地倉庫的配置方式

    這篇文章主要介紹了關(guān)于maven本地倉庫的配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • 淺談@FeignClient中name和value屬性的區(qū)別

    淺談@FeignClient中name和value屬性的區(qū)別

    這篇文章主要介紹了@FeignClient中name和value屬性的區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • 一文搞懂Runnable、Callable、Future、FutureTask及應(yīng)用

    一文搞懂Runnable、Callable、Future、FutureTask及應(yīng)用

    一般創(chuàng)建線程只有兩種方式,一種是繼承Thread,一種是實(shí)現(xiàn)Runnable接口,在Java1.5之后就有了Callable、Future,這二種可以提供線程執(zhí)行完的結(jié)果,本文主要介紹了Runnable、Callable、Future、FutureTask及應(yīng)用,感興趣的可以了解一下
    2023-08-08
  • Spring自帶的校驗(yàn)框架Validation的使用實(shí)例

    Spring自帶的校驗(yàn)框架Validation的使用實(shí)例

    今天小編就為大家分享一篇關(guān)于Spring自帶的校驗(yàn)框架Validation的使用實(shí)例,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • Java發(fā)送https請(qǐng)求并跳過ssl證書驗(yàn)證方法

    Java發(fā)送https請(qǐng)求并跳過ssl證書驗(yàn)證方法

    最近在負(fù)責(zé)一個(gè)對(duì)接第三方服務(wù)的事情,在對(duì)接期間因?yàn)榈谌椒?wù)為https的請(qǐng)求,這篇文章主要給大家介紹了關(guān)于Java發(fā)送https請(qǐng)求并跳過ssl證書驗(yàn)證的相關(guān)資料,需要的朋友可以參考下
    2023-11-11
  • MyBatis Plus整合Redis實(shí)現(xiàn)分布式二級(jí)緩存的問題

    MyBatis Plus整合Redis實(shí)現(xiàn)分布式二級(jí)緩存的問題

    Mybatis內(nèi)置的二級(jí)緩存在分布式環(huán)境下存在分布式問題,無法使用,但是我們可以整合Redis來實(shí)現(xiàn)分布式的二級(jí)緩存,這篇文章給大家介紹MyBatis Plus整合Redis實(shí)現(xiàn)分布式二級(jí)緩存,感興趣的朋友跟隨小編一起看看吧
    2023-11-11
  • Scala入門之List使用詳解

    Scala入門之List使用詳解

    這篇文章主要介紹了Scala入門之List使用詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • IDEA安裝阿里巴巴編碼規(guī)范插件的兩種方式詳解(在線安裝和離線安裝)

    IDEA安裝阿里巴巴編碼規(guī)范插件的兩種方式詳解(在線安裝和離線安裝)

    這篇文章主要介紹了IDEA安裝阿里巴巴編碼規(guī)范插件的兩種方式詳解(在線安裝和離線安裝),本文通過截圖給大家展示的非常詳細(xì),需要的朋友可以參考下
    2021-09-09
  • Eclipse 使用Maven構(gòu)建SpringMVC項(xiàng)目

    Eclipse 使用Maven構(gòu)建SpringMVC項(xiàng)目

    本文主要介紹在Eclipse下創(chuàng)建Maven項(xiàng)目構(gòu)建SpringMVC框架的過程,講解的比較詳細(xì),需要的朋友可以參考下。
    2016-06-06
  • Java中的System.getProperty()詳解

    Java中的System.getProperty()詳解

    System.getProperty("XXX")方法用來讀取JVM中的系統(tǒng)屬性,那么java 虛擬機(jī)中的系統(tǒng)屬性使用在運(yùn)行java程序的時(shí)候java -D配置,有兩種方式,一種是在命令行配置另一種是在IDE中配置,本文給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2023-09-09

最新評(píng)論