在前面的文章中讲了基于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