java socket 输入输出流_记录 serverSocket socket 输入,输出流,关闭顺序,阻塞,PrintWriter的一些问题....

本文探讨了Java Socket编程中关于OutputStream的flush问题,解释了为何选择PrintWriter而非BufferedWriter与socket.getOutputStream()配合。由于接收方使用BufferedReader的readLine,不自动换行会导致阻塞,因此需要手动调用newLine。此外,详细阐述了流关闭对socket的影响,强调了一次完整IO操作后才关闭流的重要性,并通过ServerSocketTest和SocketClient测试类展示了读写操作的实现。
摘要由CSDN通过智能技术生成

关于socket.getOutputStream() 的一些问题, OutputStream的flush是一个空方法,所以需要另一个实现了Flush的流来包装一下

这里为什么使用PrintWriter,而不使用BufferedWriter

原因是在接收方使用BufferedReader 的readLine,而BufferedWriter.write并不会自动换行,所以会导致读取阻塞,需要手动换行,代码如下:

BufferedWriter bw = new BufferedWriter(newOutputStreamWriter(socket.getOutputStream()));

bw.write("你好啊");//因为在服务端使用的是readLine,所以如果不调用newLine,那么会一直阻塞

bw.newLine();

bw.flush();

以下两个测试类代码,在输出数据的时候,输出空行为结束符,在读取输入流的时候都在循环内判断了readLine长度是否为0(当然规范的做法是约定长度,根据长度判断是否结束),原因如下摘抄☞:点击这里

对于socket,不能认为把某次写入到流中的数据读取完了就算流结尾了,但是socket流还存在,还可以继续往里面写入数据然后再读取。所以用BufferedReader封装socket的输入流,调用BufferedReader的readLine方法是不会返回null的

所以在循环内如果不判断   msg!=null&&msg.length()>0  那么程序将会一直阻塞在这里(程序是因为readLine阻塞,并不是死循环)

关于流的关闭会影响socket的使用,而且对一次连接关闭流以后,没有办法再次打开,哪怕只关闭输入流,也会导致输出流不能使用.反之亦然.

所以如果在一次IO操作以后,还有另一次IO,那么就先不关闭.等全部用完再关闭.

ServerSocket

@RunWith(JUnit4.class)public classServerSocketTest {

@Testpublic voidtestServer(){

ServerSocket serverSocket= null;try{

serverSocket= newServerSocket();//serverSocket.setReuseAddress(true);//System.out.println(InetAddress.getLocalHost());//获取的本机地址不一定正确

serverSocket.bind(new InetSocketAddress(8000));while(true){//一旦连接,返回的socket包含客户端信息的socket

Socket socket =serverSocket.accept();

PrintWriter pw= new PrintWriter(socket.getOutputStream(),true);

pw.println("host:"+socket.getInetAddress()+":"+socket.getPort()+"建立链接");//这里发送空行作为结束符,当然规范做法是根据长度作为标识

pw.println("");//因为new PrinWriter的时候指定了autoFlush的参数为true所以不用手动flush//pw.flush();

BufferedReader br = new BufferedReader(newInputStreamReader(socket.getInputStream()));for(String msg = br.readLine();msg!=null&&msg.length()>0;msg =br.readLine()){

System.out.println(msg);

}

pw.close();

br.close();

}

}catch(IOException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

}

ClientSocket

/***

*@authorlzw

**/@RunWith(JUnit4.class)public classSocketClient {

@Testpublic void testClient() throwsUnknownHostException, IOException{//表示连接到服务器的 地址以及端口

SocketAddress address = new InetSocketAddress("19.95.103.112",8000);

Socket socket= newSocket();

socket.connect(address,60000);//连接//读取服务端返回的数据

getMsb(socket);

sendMsg(socket);

socket.close();

}private voidsendMsg(Socket socket){

PrintWriter pw= null;//BufferedWriter bw = null;

try{//bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));//bw.write("你好啊");//因为在服务端使用的是readLine,所以如果不调用newLine,那么会一直阻塞//bw.newLine();//bw.flush();//OutputStream os = socket.getOutputStream();// //这个是一个空方法//os.flush();

pw = new PrintWriter(socket.getOutputStream(),true);

pw.println("你好啊");

//输出空行作为结束标识

pw.println("");//因为new PrinWriter的时候指定了autoFlush的参数为true所以不用手动flush//pw.flush();

} catch(IOException e) {

e.printStackTrace();

}finally{//因为本次连接,到这个方法以后没有更多交互,所以可以关闭

if(pw!=null){

pw.close();

}

}

}private voidgetMsb(Socket socket){

InputStream is= null;

BufferedReader br= null;try{

is=socket.getInputStream();

br= new BufferedReader(newInputStreamReader(is));for(String msg = br.readLine();msg!=null&&msg.length()>0;msg =br.readLine()){

System.out.println(msg+"--");

}

}catch(IOException e) {

e.printStackTrace();

}finally{//这里不能关闭流,否则会把socket也关闭了(因为后面还要发送数据,所以不能关闭流,不管是关闭输入输入其中之一,都会导致输入和输出都不能使用)//try {//if(br!=null)//br.close();//} catch (IOException e) {//e.printStackTrace();//}

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值