java网络编程之服务端客户端socket简单通信案例

java网络编程之服务端客户端socket简单通信案例

    近来在看《java核心技术卷II》,今晚看到第三章:网络,就忽然想起了多年前(没那么夸张,大约两年前吧),入门socket时候的案例,于是乎,就再写了一遍,就当做是温习吧!

    需求是这样的:“服务端开启服务,等待客户端的连接请求,建立了连接之后,客户端发送信息给服务端,服务端接收到之后打印该信息;之后服务端发送一条信息返回给客户端,客户端接收到之后打印出该信息!”。

    实现过程,遇到了之前遇到的问题:只是“服务端收到了客户端的信息,但是客户端却收不到服务端发送回来的信息”!后来找了原因:原来是服务端开启服务之后,就一直在处于读阻塞(空等待),当建立连接之后,客户端发送信息给服务端,此时由于客户端没有关闭写数据流,导致服务端一直在读啊读啊。。。始终读不到末尾,即-1,所以你会发现eclipse下面的”红色小块”一直在等着,因为服务端以为客户端还在一直传数据。。。。知道你关闭了“红色小块”,会出现“Connection reset”的错误!

     原来的代码:

package com.steadyjack.network;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author 钟林森
 * 服务端socket
 */
public class MyServerSocket {
	public static void main(String[] args)throws Exception{
		new MyServerSocket();
	}
	
	public MyServerSocket() throws Exception {
		ServerSocket serverSocket=null;
		Socket socket=null;
		
		try {
			serverSocket=new ServerSocket(8090);
			socket=serverSocket.accept();
			InputStream is=socket.getInputStream();
			
			byte[] bytes=new byte[1024];
			int len;
			while((len=is.read(bytes))!=-1){
				System.out.println(new String(bytes, 0, len));
			}
			
			String strVal="服务端发来慰问: 客户端你好!";
			OutputStream os=socket.getOutputStream();
			os.write(strVal.getBytes());
			
		} catch (Exception e) {
			System.out.println(e.getMessage());
		} finally{
			socket.close();
			serverSocket.close();
			
		}
	}
}

package com.steadyjack.network;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
 * @author 钟林森
 * 客户端socket
 */
public class MyClientSocket {
	public static void main(String[] args)throws Exception{
		new MyClientSocket();
	}
	
	public MyClientSocket() throws Exception{
		Socket socket=null;
		
		try {
			//建立与服务器连接的socket
			socket=new Socket("127.0.0.1", 8090);
			
			//写数据到服务端:建立写数据流,往流写数据
			String strVal="客户端送来慰问: 服务端你好!";
			OutputStream os=socket.getOutputStream();
			os.write(strVal.getBytes());
			
			InputStream is=socket.getInputStream();
			byte[] bytes=new byte[1024];
			int len;
			while((len=is.read(bytes))!=-1){
				System.out.println(new String(bytes,0,len));
			}
			
		} catch (Exception e) {
			System.out.println(e.getMessage());
		} finally{
			socket.close();
		}
	}
}
    出现如下结果,这是服务端运行后出现的结果。


    点击箭头所指,切换到客户端运行结果:


     从上面的描述中,也就知道了问题出现的原因:客户端写数据到写数据流后,没有及时关闭数据流,使得服务端一直处于读阻塞,更别说其后面还有写的需求。所以就针对这个下手,为客户端的socket提供了“及时关闭写数据流的方法”:shutdownOutput。

     下面是改进后的代码:服务端无需变动,客户端变动如下:

package com.steadyjack.network;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
 * @author 钟林森
 * 客户端socket
 */
public class MyClientSocket {
	public static void main(String[] args)throws Exception{
		new MyClientSocket();
	}
	
	public MyClientSocket() throws Exception{
		Socket socket=null;
		
		try {
			//建立与服务器连接的socket
			socket=new Socket("127.0.0.1", 8090);
			
			//写数据到服务端:建立写数据流,往流写数据
			String strVal="客户端送来慰问: 服务端你好!";
			OutputStream os=socket.getOutputStream();
			os.write(strVal.getBytes());
			
			//写关闭,不然会影响读:不然会一直阻塞着,服务器会认为客户端还一直在写数据
			//由于从客户端发送的消息长度是任意的,客户端需要关闭连接以通知服务器消息发送完毕,如果客户端在发送完最后一个字节后
			//关闭输出流,此时服务端将知道"我已经读到了客户端发送过来的数据的末尾了,即-1",就会读取出数据并关闭服务端的读数据流,在之后就可以
			//自己(服务端)的输出流了,往客户端写数据了
			socket.shutdownOutput(); 
			
			InputStream is=socket.getInputStream();
			byte[] bytes=new byte[1024];
			int len;
			while((len=is.read(bytes))!=-1){
				System.out.println(new String(bytes,0,len));
			}
			
		} catch (Exception e) {
			System.out.println(e.getMessage());
		} finally{
			socket.close();
		}
	}
}

     最终运行结果如下:

     客户端程序运行结果:


     服务端程序运行结果:



     对了,要记得“需要先运行服务端程序,在运行客户端程序。不然会报“Connection refused:connect”,就像下面这样:

java网络编程之服务端客户端socket简单通信案例_第1张图片

     搞完了,我要继续往下看了!!

你可能感兴趣的:(java)