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

作者:godelgnis 时间:2022-06-16 14:33:14 

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接口。

来源:https://blog.csdn.net/godelgnis/article/details/84258285

标签:Java,socket,getInputStream,阻塞
0
投稿

猜你喜欢

  • MyBatis中的模糊查询语句

    2022-09-30 03:36:59
  • Java实现inputstream流的复制代码实例

    2021-08-30 11:52:11
  • Activiti7整合Springboot使用记录

    2022-11-11 06:17:24
  • Mybatis日志模块的适配器模式详解

    2023-11-26 12:45:32
  • C#集合查询Linq在项目中使用详解

    2022-09-16 13:50:09
  • Java中BigDecimal类的使用详解

    2021-12-13 05:30:52
  • Android 顶部标题栏随滑动时的渐变隐藏和渐变显示效果

    2023-11-26 07:48:39
  • 浅析C#中的Main(String[] args)参数输入问题

    2023-08-13 01:45:58
  • Java实现俄罗斯方块的源码分享

    2023-02-17 04:20:48
  • C#使用GUID(全局统一标识符)

    2022-08-23 10:25:25
  • java实现轻量型http代理服务器示例

    2021-10-05 18:14:20
  • Javaweb动态开发最重要的Servlet详解

    2023-04-09 20:11:17
  • idea全局搜索快捷键超详细总结(推荐!)

    2021-08-12 20:16:18
  • java 出现Zipexception 异常的解决办法

    2022-11-07 11:03:03
  • Bean Searcher配合SpringBoot的使用详解

    2022-06-21 23:49:00
  • 浅谈Java编程中string的理解与运用

    2021-05-31 22:15:44
  • Java中泛型的用法总结

    2023-03-03 08:54:47
  • mybatis-plus用insertBatchSomeColumn方法批量新增指定字段

    2022-03-02 10:20:58
  • C#中Socket通信用法实例详解

    2022-07-10 03:42:03
  • Java 十大排序算法之希尔排序刨析

    2021-11-16 09:27:31
  • asp之家 软件编程 m.aspxhome.com