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 网络编程 说明: 网络编程,分为两种一种是TCP、另一种是UDP方式。我们分别写一下TCP、UDP端的Server和Client简单演示代码。 TCP: Sever import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; public class TCPServer { public static void main(String[] args) { try { ServerSocket socket = new ServerSocket(4444); while (true) { Socket sc =socket.accept(); InputStream instr = sc.getInputStream(); DataInputStream dataInputStream = new DataInputStream(instr); System.out.println(dataInputStream.readUTF()); } } catch (IOException e) { e.printStackTrace(); } } } Client import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; public class TCPClient { public static void main(String[] args) { try { Socket socket = new Socket("127.0.0.1",4444); OutputStream oStream = socket.getOutputStream(); DataOutputStream dataOutputStream = new DataOutputStream(oStream); dataOutputStream.writeUTF("Hello"); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } UDP: Server: import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; public class UDPServer { public static void main(String[] args) { try { byte [] buffer = new byte[1024]; DatagramSocket socket = new DatagramSocket(4444); DatagramPacket packet = new DatagramPacket(buffer, buffer.length); while(true){ socket.receive(packet); System.out.println(new String(buffer,0,packet.getLength())); } } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } Client import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.SocketException; public class UDPClient { public static void main(String[] args) { byte [] buffer = null; buffer = new String("hello").getBytes(); DatagramPacket packet=null; try { packet = new DatagramPacket(buffer, buffer.length,new InetSocketAddress("127.0.0.1", 4444)); DatagramSocket socket = new DatagramSocket(1234); socket.send(packet); socket.close(); } catch (SocketException e1) { e1.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

修罗debug

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值