文档章节

Java网络IO通信:Socket

伤了心的蜻蜓在唱歌
 伤了心的蜻蜓在唱歌
发布于 2017/03/29 10:29
字数 1148
阅读 14
收藏 0

1. Socket通信原理

Socket的底层数据传输使用的是SocketStream,本质上还是属于IO流。Socket的通信分为客户端和服务器端。客户端主要向服务器端发送请求和接受返回值;服务器端用于接收客户端请求,处理请求及返回处理结果。下面从两个方面介绍其基本原理:

1.1  服务器端的流程

1)服务器端首先要启动监听。监听使用的类ServerSocket,创建该类的实例,然后调用bind方法绑定监听的IP地址和端口号。然后调用accept方法进行监听,此时IO阻塞一直到有请求。

2)当服务器端监听到客户端的请求,则accept方法会返回一个Socket对象,这时候已经与客户端建立了Socket通道,使用Socket的getInputStream()方法获取通道输入流,通过输入流获取客户端发送的请求数据。

3)获取客户端的请求数据后,服务器开始调用相应的方法等来处理。接着使用socket获取输出流getOutputStream(),将结果写回到客户端。

4)最后一步,关闭输入输出流及socket通道。

需要注意的是:使用socketinputstream读取数据都是祖阻塞的。

1.2 客户端流程

 1)创建Socket对象,该对象绑定到服务器监听的IP地址和端口号。

 2)同样用getInoutStream和getOutputStream获取输入输出流接受数据和发送数据。

总结:从上述流程可以看出,在服务器端只需要使用ServerSocket进行监听客户端请求,实际的通信是由Socket底层的输入输出流完成的。Socket很大的缺点是读取数据时会发生阻塞。

 

2. Socket的实例

在该实例中有详细的代码注解。

服务器端代码的实现:

package com.dd171290.socket;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class UserServer {

	
	@SuppressWarnings("resource")
	public static void main(String[] args) throws IOException {
		//服务器端监听客户端的请求,使用的类是ServerSocket
		ServerSocket serverSocket=new ServerSocket();
		//绑定监听的ip地址和端口号
		serverSocket.bind(new InetSocketAddress("localhost", 9920));
		//开始监听客户端请求,此时IO阻塞,一直到有新的请求时被激活,为了能够处理多客户端发来的请求
		//使用线程来处理每一次请求的业务
		while(true){
			Socket socket=serverSocket.accept();
			new Thread(new ServiceDeal(socket)).start();
		}
	}
}

线程的业务处理类,通过反射实现目标类的调用:

package com.dd171290.socket;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.net.Socket;

public class ServiceDeal implements Runnable {

	Socket socket;
	InputStream inputStream=null;
	OutputStream outputStream=null;
	public ServiceDeal(Socket socket) {
		this.socket=socket;
	}

	public void run() {
		//开始处理业务逻辑
		
		//先获取到客户端的请求输入流
		try {
			inputStream=socket.getInputStream();
			BufferedReader reader=new BufferedReader(new InputStreamReader(inputStream));
			//从网络中读取客户端发送过来的数据流
			//使用socketinputstream读取数据都是祖阻塞的。
			String request=reader.readLine();
			
			//获取到了请求数据后,开始调用相对应的业务逻辑处理,这里采用的是反射来处理业务并将结果放回给客户端。
			//为了方便,这里约定用空格来分割不同的参数
			String [] params=request.split(" ");
			String className=params[0].trim();//服务端调用类所在包的路径
			String method=params[1].trim();//调用方法的名字
			String arg=params[2].trim();//默认传递一个参数
			System.out.println("packages:"+className);
			System.out.println("method:"+method);
			System.out.println("args:"+arg);
			
			//获取Class对象
			Class<?> service=Class.forName(className);
			Object data=service.newInstance();
			Method method1=service.getMethod(method, String.class);
			Object result=method1.invoke(data, arg);
			System.out.println("返回的结果:"+result);
			
			//将结果返回给客户端
			System.out.println("开始向客户端返回结果!");
			outputStream=socket.getOutputStream();
			PrintWriter pWriter=new PrintWriter(outputStream);
			pWriter.println(result.toString());
			pWriter.flush();
			System.out.println("向客户端发送数据结束!!");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				outputStream.close();
				inputStream.close();
				if(socket!=null)
				   socket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

业务处理的目标类:

package com.dd171290.socket;

public class ReflectData {

	public String welcome(String msg) {
		return "welcome:"+msg;
	}
}

客户端代码实现:

package com.dd171290.socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class UserClient {

	
	public static void main(String[] args) throws Exception {
		// 向客户端发送请求
		Socket socket=new Socket("localhost", 9920);
		//获取输出流,发送数据
		PrintWriter pWriter=new PrintWriter(socket.getOutputStream());
		String mSg="com.dd171290.socket.ReflectData welcome client!";
		pWriter.println(mSg);
		pWriter.flush();
		
		
		//从服务器端读取返回的结果
		BufferedReader bReader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
		String result=bReader.readLine();
		System.out.println(result);
	}
	
}

 

先启动服务端,运行的结果为:

packages:com.dd171290.socket.ReflectData
method:welcome
args:client!
返回的结果:welcome:client!
开始向客户端返回结果!
向客户端发送数据结束!!

客户端运行的结果:

welcome:client!

 

© 著作权归作者所有

伤了心的蜻蜓在唱歌
粉丝 0
博文 9
码字总数 9841
作品 0
开封
私信 提问
分布式Java--基于消息方式实现系统间通信

分布式系统之间通信可以分为两种: 基于消息方式实现系统间通信 基于远程调用方式实现系统间通信 基于消息方式实现系统间通信 分布式子系统之间需要通信时,就发送消息。一般通信的两个要点是...

akane_oimo
2018/09/14
59
0
Qzone 微信 Java高级——dubbo源码分析之远程通信 netty

Java高级——dubbo源码分析之远程通信 netty dubbo 底层通信选择了 netty 这个 nio 框架做为默认的网络通信框架并且通过自定义协议进行通信。dubbo 支持以下网络通信框架: Netty(默认) Min...

Java架构师那些事
2018/08/29
0
0
Apache Mina 网络通信

Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP、UDP/IP协议栈的通信框架(当然,也可以提供JAVA 对象的序列化服务、虚拟机管道通信服务等),Mina 可以帮助我...

Mr&Cheng
2013/01/20
350
0
Java NIO 和 IO的区别

Java NIO 和 IO的区别 Java IO 中,ServerSocket 负责绑定 IP 地址,启动监听端口;Socket 负责发起连接操作,连接成功后,双方通过输入和输出流进行同步阻塞通信。采用 BIO 通信模型的 Serv...

秋风醉了
2014/11/01
352
0
java基础专栏—java网络编程

java网络编程 在网络成层中TCP对应于四层 通常是对网络连接设备的驱动协议,例如对光纤和都对网线的驱动不一样 TCP/IP协议的核心,他用于将数据分组 包括TCP,UDP 主要是负责应用程序的协议。...

T-newcomer
2017/10/25
85
0

没有更多内容

加载失败,请刷新页面

加载更多

精华帖

第一章 jQuery简介 jQuery是一个JavaScript库 jQuery具备简洁的语法和跨平台的兼容性 简化了JavaScript的操作。 在页面中引入jQuery jQuery是一个JavaScript脚本库,不需要特别的安装,只需要...

流川偑
10分钟前
3
0
语音对话英语翻译在线翻译成中文哪个方法好用

想要进行将中文翻译成英文,或者将英文翻译成中文的操作,其实有一个非常简单的工具就能够帮助完成将语音进行翻译转换的软件。 在应用市场或者百度手机助手等各大应用渠道里面就能够找到一款...

401恶户
21分钟前
1
0
jenkins 插件下载加速最终方案

推荐做法 1、告诉jenkins 我哪些插件需要更新 jenkins插件清华大学镜像地址 https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json 1.进入jenkins系统管理 2.进入插件管...

vasks
27分钟前
3
0
composer爆错:zlib_decode():data error

解决办法:先用 composer diagnose 命令检测 然后 composer self-update 更新composer版本 最后执行 composer update 或者 composer install composer 切换阿里云镜像 用起来还快 composer c...

koothon
34分钟前
3
0
shangcheng-my

1.数据库主键、外键类型为bigint,那么在后台应该用什么类型的变量定义? 后台用string接收,因为前段传过来的一般都是json字符串,后台直接接收,mysql是可以吧数字类型的字符串转换为对应的...

榴莲黑芝麻糊
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部