欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

解决Java中socket使用getInputStream()阻塞问题

程序员文章站 2022-03-05 17:44:48
目录socket使用getinputstream()阻塞用线程解决socket的getinputstream阻塞1.背景2.问题3.原因4.解决办法5.socket通信注意事项socket使用geti...

socket使用getinputstream()阻塞

今天用socket进行编程练习时,发现程序到了getinputstream()这里就进行不下去了

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());

就这样的一个测试代码,a不会打印出来

后来发现是getinputstream()会一直阻塞在那里阻塞

我把两行代码调了一下就好了,还不太清楚原因,先记下来

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通信中,当我们希望传输对象时,往往会用到输入/输出对象流。

objectinputstream in=new objectinputstream(socket.getinputstream());
objectoutputstream out=new objectoutputstream(socket.getoutputstream());

2.问题

当程序调用socket.getinputstream()程序被被卡住。

3.原因

socket.getinputstream()方法会导致程序阻塞,直到inputstream收到对方发过来的报文消息,程序才会继续往下执行。

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.");
	} 
}

//============服务器端代码 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通信注意事项

(1).writexxx()方法后一般用flush()来把缓存内容发送出去。

(2).发送对象时,对象必须串行化,即该对象需要实现serializable接口。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。