基于I/O的Server/Client实现

Posted zhchoutai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于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

以上是关于基于I/O的Server/Client实现的主要内容,如果未能解决你的问题,请参考以下文章

Java NIO使用及原理分析

PHP实现查看邮件是否被阅读

Java NIO使用及原理分析 来自网上资料整理

Java: server/client 心跳机制实现 示例

基于select模型的udp客户端实现超时机制

NIO提升系统性能