基于I/O的Server/Client实现

在前面的文章中讲了基于NIO实现的Server/Client。本文就讲讲基于同步堵塞式I/O实现的Server/Client好与前面的NIO中的Server/Client进行对照。

网络编程中须要解决的两个主要问题:

1、怎样准确的定位网络上的一台或多台主机。

2、找到主机后怎样可靠高效的进行传输数据。

而解决这两个问题的主要方式就是非常好的运用TCP/IP协议。所以我们所做的网络编程都是基于TCP/IP来实现的。

基于Socket的java网络编程的通信过程:

server:使用ServerSocket监听它指定的port,等待client连接请求。client连接后,产生会话,在会话结束之后。关闭连接。

client:使用Socket对网络的某一服务的某一port发出连接请求。一旦连接成功。打开会话,会话完毕之后,关闭连接。

对一个功能齐全的Socket,都要包括下面的基本结构,当中过程包括下面四步:

1、创建Socket

2、打开连接到Socket的输入输出流

3、依照一定的协议对Socket进行读/写操作

4、关闭Socket

详细代码示比例如以下:

实现单线程

server端程序:

package IOSocket;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * server的工作就是在指定的端口上监听
 * 建立连接
 * 打开输出流
 * 封装输出流
 * 向client发送数据
 * 关闭打开的输出流
 * 关闭打开的Socket对象
 * server端的程序,在while循环中所运行的动作
 * 听。说,听,说...
 * @author Administrator
 *
 */
public class Server2 {
	private static final int port = 12345;
	public static void main(String[] args) {
		try {
			ServerSocket ss = new ServerSocket(port);
			//socket对象调用accept方法,等待请求的连接
			System.out.println("server已启动,等待请求...");
			Socket s = ss.accept();
			//打开并封装输出流
			DataOutputStream dos = new DataOutputStream(s.getOutputStream());
			//打开并封装输入流
			DataInputStream dis = new DataInputStream(s.getInputStream());
			//封装并读取键盘上的输入流
			BufferedReader br = new BufferedReader
					(new InputStreamReader(System.in));
			String info;
			while(true){
				//接收client发过来的信息
				info = dis.readUTF();
				System.out.println("client说:"+info);
				//假设发现对方说bye,则结束会话
				if(info.equals("bye")){
					break;
				}
				//读取键盘上的输入流,写入client
				info = br.readLine();
				dos.writeUTF(info);
				//假设server自己说bye,也结束会话
				if(info.equals("bye")){
					break;
				}
			}
			dis.close();
			dos.close();
			s.close();
			ss.close();
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("网络连接异常,退出程序...");
		}
	}
}

client程序:

package IOSocket;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.Socket;

/**
 * 创建socket对象,指定server的ip地址和server监听的端口号
 * client在new的时候,就发出了连接请求,server端就会进行处理
 * client在while循环中运行操作:
 * 听,说,听,说...
 *
 */
public class Client2 {
	private final static String host = "localhost";
	private final static int port = 12345;
	public static void main(String[] args) {
		try {
			Socket s = new Socket(host,port);
			System.out.println("client启动,发送请求...");
			//打开并封装输出流
			DataOutputStream dos = new DataOutputStream(s.getOutputStream());
			//打开并封装输入流
			DataInputStream dis = new DataInputStream(s.getInputStream());
			//读取并封装键盘输入流
			BufferedReader br = new BufferedReader(
					new InputStreamReader(System.in));
			String info;
			while(true){
				//client先读取键盘输入信息
				info = br.readLine();
				//写入到server
				dos.writeUTF(info);
				//假设client自己说bye,即结束对话
				if(info.equals("bye")){
					break;
				}
				//接收server端信息
				info = dis.readUTF();
				System.out.println("server说: "+ info);
				if(info.equals("bye")){
					break;
				}
			}
			dis.close();
			dos.close();
			s.close();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

实现多线程

服务端程序:

package IOSocket;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class Server3 {
	private final static int port = 12345;
	public static void main(String[] args) {
		ServerSocket ss = null;
		Socket s = null;
		try {
			System.out.println("server端启动,等待...");
			ss = new ServerSocket(port);
			 s = ss.accept();
			//打开并封装输出流
			DataOutputStream dos = new DataOutputStream(s.getOutputStream());
			//打开并封装输入流
			DataInputStream dis = new DataInputStream(s.getInputStream());
			new Thread(new MyServerReader(dis)).start();
			new Thread(new MyServerWriter(dos)).start();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
//接受并打印client传过来的信息
class MyServerReader implements Runnable{
	private DataInputStream dis;
	public MyServerReader(DataInputStream dis){
		this.dis = dis;
	}
	@Override
	public void run() {
		String info;
		while(true){
			//假设对方,即client没有说话,那么就会堵塞在这里
			//可是这里的堵塞并不会影响其他的线程
			try {
				info = dis.readUTF();
				//假设状态由堵塞变为非堵塞,那么就答应接收到的信息
				System.out.println("client说:"+info);
				if("bye".equals(info)){
					System.out.println("退出程序!");
					System.exit(0);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
//从键盘获取输入流并写入信息到client
class MyServerWriter implements Runnable{
	private DataOutputStream dos;
	public MyServerWriter(DataOutputStream dos){
		this.dos = dos;
	}
	@Override
	public void run() {
		//读取键盘上的输入流
		InputStreamReader isr = new InputStreamReader(System.in);
		//封装键盘的输入流
		BufferedReader br = new BufferedReader(isr);
		String info;
		while(true){
			try {
				info = br.readLine();
				dos.writeUTF(info);
				if("bye".equals(info)){
					System.out.println("自己退出程序!");
					System.exit(0);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

client程序:

package IOSocket;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

public class Client3 {
	private final static String host = "localhost";
	private final static int port = 12345;
	public static void main(String[] args) {
		Socket s = null;
		try {
			s = new Socket(host,port);
			System.out.println("client启动,发送消息...");
			//打开并封装输入流
			DataInputStream dis = new
					DataInputStream(s.getInputStream());
			//打开并封装输出流
			DataOutputStream dos = new DataOutputStream(s.getOutputStream());
			new Thread(new MyClientReader(dis)).start();
			new Thread(new MyClientWriter(dos)).start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
//接收server端传过来的信息
class MyClientReader implements Runnable{
	private DataInputStream dis;
	public MyClientReader(DataInputStream dis){
		this.dis = dis;
	}
	@Override
	public void run() {
		String info;
		while(true){
			try {
				info = dis.readUTF();
				System.out.println("server说:"+info);
				if("bye".equals(info)){
					System.out.println("对方下线,退出程序!");
					System.exit(0);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
//从键盘获得输入流并写入信息到服务端
class MyClientWriter implements Runnable{
	private DataOutputStream dos;
	public MyClientWriter(DataOutputStream dos){
		this.dos = dos;
	}
	@Override
	public void run() {
		InputStreamReader isr = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(isr);
		String info;
		while(true){
			try {
				info = br.readLine();
				dos.writeUTF(info);
				if("bye".equals(info)){
					System.out.println("自己下线,退出程序!");
					System.exit(0);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

參考资料:http://www.cnblogs.com/hongten/archive/2012/04/29/java_socket.html

时间: 2024-12-18 20:21:34

基于I/O的Server/Client实现的相关文章

SQL Server虚拟化系列(3)——构建理想的基于VMware的SQL Server虚拟机

虚拟化变得越来越常见,并且在不了解虚拟化如何工作的情况下,DBA在尝试解决性能问题时会出现盲点,例如减少资源争用或改进备份和恢复操作等. 在本文中我们将主要讲述为您的SQL Server工作负载构建理想的基于VMware的虚拟机.我们的下一篇文章将介绍怎么样在Hyper-V上构建对应的SQL Server虚拟化环境. 现在,作为DBA,您可能没有访问权限来创建用于SQL Server的新虚拟机.这些操作可以交给您的VM管理员,他们将为您部署合适的VM环境. 以下详细信息适用于在Windows S

Consul集群Server+Client模式

Consul集群Server+Client模式 架构示意图 只使用Consul的Server模式有以下2个问题: 因为Consul Server数量受到控制所以压力承载(扩展性)是个问题. Server很少导致一个Server下会注册很多微服务,当Server挂掉,这个Server节点下注册的微服务都会视为无效. 基于上述问题我们在架构中加入Consul Client模式,Client因为加入了LAN gossip协议组成网络中(高速局域网),可以识别故障的Server节点并找到可用的Serve

用XMLRPC开服务进行server/client通信

本文讲一下如何用python的xmlrpc开服务,进行server/client的通信. 应用场景:1)需多client访问应用程序给予应答情况--网页服务:  2)数据极大,希望加载一次,后面只用方法调用 解决方案:  开两个服务,一个数据服务,一个网络服务:  数据服务端加载数据,网络服务端调用数据,并将结果显示在网络服务中:  外部调用网络服务返回结果: 应用工具:xmlrpc,本文中以python 2.7.3的xmlrpclib为例,其他语言也有相应接口 下面分别说明. 1. 数据端 在

NetMQ(ZeroMQ)Client => Server => Client 模式的实现

ØMQ (也拼写作ZeroMQ,0MQ或ZMQ)是一个为可伸缩的分布式或并发应用程序设计的高性能异步消息库.它提供一个消息队列, 但是与面向消息的中间件不同,ZeroMQ的运行不需要专门的消息代理(message broker).该库设计成常见的套接字风格的API. ZeroMQ是由iMatix公司和大量贡献者组成的社群共同开发的.ZeroQ通过许多第三方软件支持大部分流行的编程语言 .类库提供一些套接字(对传统Berkeley套接字和Unix domain socket的泛化),每一个套接字可

基于Libevent的HTTP Server

简单的Http Server 使用Libevent内置的http相关接口,可以很容易的构建一个Http Server,一个简单的Http Server如下: #include <event2/event.h> #include <event2/buffer.h> #include <event2/http.h> #include <Winsock2.h> #include <stdlib.h> #include <stdio.h> i

C Socket Programming server client

用C语言socket编程写简单的server和client程序,目的为了测试一次socket连接中,数据从client端开始发送至server端接受完毕所耗的时间,以及找到原因和提升性能.这里贴出代码,make以后,直接运行server和client即可. sever.c /************************************ * For msmr * server_s.c * tesing the speed of socket * 2015-02-04 * [email 

Windows下使用FileZilla[Server+Client]搭建FTP服务

FTP服务器,客户端开源的,商业的非常多,尝试过不少,真心觉得FileZilla不错,流行,开源,稳定,安全,高性能. 下面通过图示的方式说明快速上手FileZilla,这里插播几句话,关于FTP的可以另作了解,而FileZilla可以看作是两款普通的配套来用的软件(Server+Client). 1.下载软件包 FileZilla Server:https://filezilla-project.org/download.php?type=server FileZilla Client: ht

vCenter Server Client 5.5的安装

最近发现MDT推出去的系统的有不同问题,其问题就不说了,主要是策略权限被域继承了.比如我们手动安装的很多东东都是未配置壮态,推的就默认为安全壮态了,今天细找了一下,原来把这个关了就可以了. vCenter Server Client 5.5的安装

基于群集的Hyper-v Server副本

基于群集的Hyper-v Server副本 前面的博文中和大家聊了Hyper-v副本,相信大家对Hyper-v副本已经有了一个大致了解!今天我们就来给大家介绍一下基于群集的Hyper-v Replica. 前面我们说过Windows Server 2012中,Hyper-v角色引入了Hyper-v副本作为虚拟机内部复制的机制.Hyper-v以异步同步的方式将主站点的虚拟机复制到辅助站点的副本虚拟机. 使用Hyper-v副本可以实现以下优势: 1.恢复能力 - 通过在不同地理位置的分支机构或区域站