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

时间:2023-01-24 22:16:00

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

    近来在看《java核心技术卷II》,今晚看到第三章:网络,就忽然想起了多年前(没那么夸张,大约两年前吧java网络编程之服务端客户端socket简单通信案例),入门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();
}
}
}
    出现如下结果,这是服务端运行后出现的结果。

java网络编程之服务端客户端socket简单通信案例
    点击箭头所指,切换到客户端运行结果:

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

     从上面的描述中,也就知道了问题出现的原因:客户端写数据到写数据流后,没有及时关闭数据流,使得服务端一直处于读阻塞,更别说其后面还有写的需求。所以就针对这个下手,为客户端的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();
}
}
}

     最终运行结果如下:

     客户端程序运行结果:

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

     服务端程序运行结果:

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


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

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

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