您的位置:首页 > 编程语言 > Java开发

一.用java编写的入门客户/服务器通信程序

2012-03-07 11:22 323 查看
 
本篇文章观点和例子来自 《Java网络编程精解》, 作者为孙卫琴, 出版社为电子工业出版社。

      Java 网络程序都采用客户/服务器通信模式, 致力于实现应用层。 传输层向应用层提供了套接字 Socket 接口, Socket 封装了下层的数据传输细节, 应用层的程序通过 Socket 来建立与远程主机的连接, 以及进行数据传输。

 

      站在应用层的角度,两个进程之间的一次通信过程从建立连接开始,接着交换数据,到断开连接结束。 套接字可看做是通信线路两端的接收器,进程通过套接字来收发数据。

      如 进程A1-------Socket <------tcp连接----->Socket-------进程B1

 

      在Java中, 有3种套接字类: java.net.Socket、java.net.ServerSocket 和 DatagramSocket。 其中 Socket 和 ServerSocket 类建立在 TCP协议基础上; DatagramSocket 类建立在UDP协议基础上。

 

 创建 EchoClient
package com.sockettest;
               

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.net.Socket;
                               

public class EchoClient {

 private String host = "localhost";//EchoServer进程所在的主机的名字,这里为"localhost"表示EchoClient和EchoServe

           //进程运行在同一个主机上.

 private int port = 8000;    //EchoServer进程监听的端口

 private Socket socket;

 

 public EchoClient() throws IOException{

  if(socket == null){

   socket = new Socket(host,port);//如果Socket对象成功创建,就表示建立了EchoClient和EchoServer之间的连接.

   System.out.println("连接服务器!");

  }

 }

 

 private PrintWriter getWriter(Socket socket) throws IOException{

  OutputStream socketOut = socket.getOutputStream();

  return new PrintWriter(socketOut,true);

 }

 

 private BufferedReader getReader(Socket socket) throws IOException{

  InputStream socketIn = socket.getInputStream();

  return new BufferedReader(new InputStreamReader(socketIn));

 }

 

 /**

  * EchoClient 类中最主要的方法. 该方法不断读取用户从控制台输入的字符串, 然后把它发送给 EchoServer, 再把EchoServer

  * 返回的字符串打印到控制台. 如果用户输入的字符串为 "bye", 就会结束与 EchoServer的通信, 调用socket.close()方法断开

  * 连接.

  */

 public void talk() {

  try{

   //EchoClient和EchoServer建立连接后, EchoClient从Socket对象中得到输出流和输入流, 就能与EchoServer交换数据.

   BufferedReader br = getReader(socket);

   PrintWriter pw = getWriter(socket);

   

   BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in));

   

   String msg = null;

   while((msg = localReader.readLine())!= null){

    pw.println(msg);   //输出信息到服务器

    System.out.println(br.readLine()); //打印从服务器接受的信息

    

    if(msg.equals("bye"))   //如果客户发送的信息为"bye",就结束通信

     break;

   }

   

   

  }catch(IOException e){

   e.printStackTrace();

  }finally{

   try{

    if(socket != null) socket.close();  //断开连接

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

  }

 }

 

 

 public static void main(String args[])throws IOException{

  new EchoClient().talk();

 }

}
 
 

创建 EchoServer
package com.sockettest;
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.net.ServerSocket;

import java.net.Socket;
public class EchoServer {
 private int port = 8000;

 private ServerSocket serverSocket;

 

 public  EchoServer() throws IOException{

  if(serverSocket == null){

   //服务器程序通过一直监听端口, 来接受客户程序的连接请求. 在服务器程序中, 需要先创建一个ServerSocket对象,

   //在构造方法中指定监听的端口.

   //ServerSocket的构造方法负责在操作系统中把当前 进程注册为服务器进程.

   serverSocket = new ServerSocket(port);          //监听8000端口

   System.out.println("服务器启动!");

  }

 }

 

 public String echo(String msg){

  return "echo:" + msg;

 }

 

 //Socket类提供getOutputStream()方法,返回输出流OutputSteam对象,程序只需向输出流写数据, 就能向对方发送数据,

 //Socket的输出流可以用过滤留来装饰, 这个方法中先获取输出流, 然后用PrintWriter装饰它, PrintWriter的

 //println()方法能够写一行数据.

 private PrintWriter getWriter(Socket socket) throws IOException{

  OutputStream socketOut = socket.getOutputStream();

  return new PrintWriter(socketOut,true);//参数true表示每写一行, PrintWriter缓存就自动溢出, 把数据写到目的地

 }

 

 //Socket类提供getInputStream()方法, 返回输入流InputStream对象, 程序只需从输入流读数据,就能接收来自对方的数据,

 //Socket的输入流也可以用过滤流来装饰, 这个方法中先获取输入流, 然后用BufferedReader装饰它, BufferedReader的

 //readLine()方法能够读入一行数据.

 private BufferedReader getReader(Socket socket) throws IOException{

  InputStream socketIn = socket.getInputStream();

  return new BufferedReader(new InputStreamReader(socketIn));

 }

 

 /**

  * EchoServer 类最主要的方法, 它不断等待客户的连接请求, 当serverSocket.accept()方法返回一个Socket对象时,

  * 就意味着与一个客户建立了连接,接下来从Socket对象中得到输出流和输入流, 并且分别用PrintWriter 和BufferedReader

  * 来装饰它们. 然后不断调用 BufferedReader 的readLine()方法读取客户发来的字符串XXX, 再调用PrintWriter 的

  * println()方法向客户返回字符串 echo:XXX. 当客户发来的字符串为 "bye" 时, 就会结束与客户的通信,

  * 调用socket.close() 方法断开连接.

  * PS.这个方法无法同时与多个客户通信. EchoServer接收到一个客户连接, 就与客户进行通信, 通信完毕后断开连接,然后再

  *    接收下一个客户连接. 假如同时有多个客户请求连接, 这些客户就必须排队等候EchoServer的响应.

  */

 public void service(){

  while(true){

   Socket socket = null;

   try{

    //服务器程序调用ServerSocket对象的accept()方法, 该方法一直监听端口, 等待客户的连接请求, 如果接受到一个

    //连接请求, accept()方法就会返回一个Socket对象, 这个Socket对象与客户端的Scoket对象形成了一条通信线路.

    socket = serverSocket.accept();    //等待客户连接

    

    //Socket对象包含了客户的地址和端口

    System.out.println("New connection accepted "

      + socket.getInetAddress()  + " : " + socket.getPort());

    

    BufferedReader br = getReader(socket);

    PrintWriter pw = getWriter(socket);

    

    String msg = null;

    while((msg = br.readLine()) != null){

     System.out.println(msg); //打印接受的信息

     pw.println(echo(msg));  //输出信息到客户
a8ea


     if(msg.equals("bye"))  //如果客户端发送的信息为"bye", 就结束通信

      break;

    }

    

   }catch(IOException e){

    e.printStackTrace();

   }finally{

    try{

     if(socket != null) socket.close();  //断开连接

    }catch(IOException e){

     e.printStackTrace();}

   }

  }

 }

 

 

 

 public static void main(String[] args) throws IOException {

  // TODO Auto-generated method stub

  new EchoServer().service();

 }
}
 
 

先运行 EchoServer,  再运行 EchoClient, 在EchoClient的控制台中输入字符串, 当输入的字符串为bye时,  就会结束与EchoServer的通信.

 

转载自:http://blog.csdn.net/lin49940/article/details/4382143
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息