JAVA总结之一:SOCKET通信(代码篇)

前言:这是我第一次开始总结我的编程之路,那么就从socket通信开始吧,本片是我原引自网络总结篇文章,我觉得比较具体精炼,代码干练,是我想要总结的类型,因此就“借鉴”以自用。如果还有更好的我会继续总结,也当是我的继续学习啦。

——levy

 

一、SOCKET原理


   1.什么是socket
   所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
   以J2SDK-1.3为例,Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。
   2.重要的Socket API:
   java.net.Socket继承于java.lang.Object,有八个构造器,其方法并不多,下面介绍使用最频繁的三个方法,其它方法大家可以见JDK-1.3文档。
   . Accept方法用于产生"阻塞",直到接受到一个连接,并且返回一个客户端的Socket对象实例。"阻塞"是一个术语,它使程序运行暂时"停留"在这个地方,直到一个会话产生,然后程序继续;通常"阻塞"是由循环产生的。
   . getInputStream方法获得网络连接输入,同时返回一个IutputStream对象实例,。
   . getOutputStream方法连接的另一端将得到输入,同时返回一个OutputStream对象实例。
   注意:其中getInputStream和getOutputStream方法均会产生一个IOException,它必须被捕获,因为它们返回的流对象,通常都会被另一个流对象使用。
   3.如何开发一个Server-Client模型的程序
   开发原理:


   服务器,使用ServerSocket监听指定的端口,端口可以随意指定(由于1024以下的端口通常属于保留端口,在一些操作系统中不可以随意使用,所以建议使用大于1024的端口),等待客户连接请求,客户连接后,会话产生;在完成会话后,关闭连接。


   客户端,使用Socket对网络上某一个服务器的某一个端口发出连接请求,一旦连接成功,打开会话;会话完成后,关闭Socket。客户端不需要指定打开的端口,通常临时的、动态的分配一个1024以上的端口。

 

二、建立模型


      

       1.基本Server-Client模型

 

   {建立服务器} 

   1: import java.net.*;
   2: import java.io.*;
   3:  
   4: public class Server {
   5:     private ServerSocket ss;
   6:     private Socket socket;
   7:     private BufferedReader in;
   8:     private PrintWriter out;
   9:  
  10:     public Server() {
  11:       try {
  12:           ss = new ServerSocket(10000);
  13:  //进入循环,这是由socket的特性决定的,进行循环监听
  14:           while (true) {
  15:               socket = ss.accept(); //accept() 监听方法
  16:               in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  17:               out = new PrintWriter(socket.getOutputStream(),true);
  18:  
  19:               String line = in.readLine();
  20:               out.println("you input is :" + line);
  21:               out.close();
  22:               in.close();
  23:               socket.close(); //socket流必须关闭!
  24:             }
  25:           ss.close();
  26:         } catch (IOException e) {}
  27:     }
  28:  
  29:     public static void main(String[] args) {
  30:       new Server();
  31:     }
  32:   }

 

这个程序建立了一个服务器,它一直监听10000端口,等待用户连接。在建立连接后给客户端返回一段信息,然后结束会话。这个程序一次只能接受一个客户连接。

{建立客户端}

   1: import java.io.*;
   2: import java.net.*;
   3: public class Client {
   4:     Socket socket;
   5:     BufferedReader in;
   6:     PrintWriter out;
   7:     public Client() {
   8:       try {
   9:           socket = new Socket("xxx.xxx.xxx.xxx", 10000);  //服务器地址和端口号
  10:           in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  11:           out = new PrintWriter(socket.getOutputStream(),true);
  12:           BufferedReader line = new BufferedReader(new InputStreamReader(System.in));
  13:           out.println(line.readLine());
  14:           line.close();
  15:           out.close();
  16:           in.close();
  17:           socket.close();
  18:         } catch (IOException e) {}
  19:     }
  20:     public static void main(String[] args) {
  21:       new Client();
  22:     }
  23:   }

 

这个客户端连接到地址为xxx.xxx.xxx.xxx的服务器,端口为10000,并从键盘输入一行信息,发送到服务器,然后接受服务器的返回信息,最后结束会话。

 

       2.Serverd端多线程模型(解决多客户同时连接)


   在实际的网络环境里,同一时间只对一个用户服务是不可行的。一个优秀的网络服务程序除了能处理用户的输入信息,还必须能够同时响应多个客户端的连接请求。在java中,实现以上功能特点是非常容易的。


   设计原理:


   主程序监听一端口,等待客户接入;同时构造一个线程类,准备接管会话。当一个Socket会话产生后,将这个会话交给线程处理,然后主程序继续监听。运用Thread类或Runnable接口来实现是不错的办法。
  

{实现消息共性} 

 

   1: import java.io.*;
   2: import java.net.*;
   3: public class Server extends ServerSocket {
   4:     private static final int SERVER_PORT = 10000;
   5:     public Server() throws IOException {
   6:         super(SERVER_PORT);
   7:         try {
   8:             while (true) {
   9:                 Socket socket = accept();
  10:                 new CreateServerThread(socket);
  11:               }
  12:           } catch (IOException e) {} finally {
  13:             close();
  14:           }
  15:       }
  16: //--- CreateServerThread
  17:     class CreateServerThread extends Thread {
  18:         private Socket client;
  19:         private BufferedReader in;
  20:         private PrintWriter out;
  21:         public CreateServerThread(Socket s) throws IOException {
  22:             client = s;
  23:             in = new BufferedReader(new InputStreamReader(client.getInputStream(), "GB2312"));
  24:             out = new PrintWriter(client.getOutputStream(), true);
  25:             out.println("--- Welcome ---");
  26:             start();
  27:           }
  28:         public void run() {
  29:           try {
  30:               String line = in.readLine();
  31:               while (!line.equals("bye")) {
  32:                   String msg = createMessage(line);
  33:                   out.println(msg);
  34:                   line = in.readLine();
  35:                 }
  36:               out.println("--- See you, bye! ---");
  37:               client.close();
  38:             } catch (IOException e) {}
  39:         }
  40:         private String createMessage(String line) {
  41:           xxxxxxxxx;
  42:         }
  43:       }
  44:     public static void main(String[] args) throws IOException {
  45:         new Server();
  46:       }
  47:   }

   

这个程序监听10000端口,并将接入交给CreateServerThread线程运行。CreateServerThread线程接受输入,并将输入回应客户,直到客户输入"bye",线程结束。我们可以在createMessage方法中,对输入进行处理,并产生结果,然后把结果返回给客户。 第三步 实现信息共享:在Socket上的实时交流

 

        2.信息共享模型


   网络的伟大之一也是信息共享,Server可以主动向所有Client广播消息,同时Client也可以向其它Client发布消息。下面看看如何开发一个可以实时传递消息的程序。

设计原理:
   服务器端接受客户端的连接请求,同时启动一个线程处理这个连接,线程不停的读取客户端输入,然后把输入加入队列中,等候处理。在线程启动的同时将线程加入队列中,以便在需要的时候定位和取出。


  {源码}

 

   1: import java.io.*;
   2: import java.net.*;
   3: import java.util.*;
   4: import java.lang.*;
   5: public class Server extends ServerSocket {
   6:     private static ArrayList User_List = new ArrayList();
   7:     private static ArrayList Threader = new ArrayList();
   8:     private static LinkedList Message_Array = new LinkedList();
   9:     private static int Thread_Counter = 0;
  10:     private static boolean isClear = true;
  11:     protected static final int SERVER_PORT = 10000;
  12:     protected FileOutputStream LOG_FILE = new FileOutputStream("d:/connect.log", true);
  13:     public Server() throws FileNotFoundException, IOException {
  14:         super(SERVER_PORT);
  15:         new Broadcast();
  16: //append connection log
  17:         Calendar now = Calendar.getInstance();
  18:         String str = "[" + now.getTime().toString() + "] Accepted a connection\015\012";
  19:         byte[] tmp = str.getBytes();
  20:         LOG_FILE.write(tmp);
  21:         try {
  22:             while (true) {
  23:                 Socket socket = accept();
  24:                 new CreateServerThread(socket);
  25:               }
  26:           } finally {
  27:             close();
  28:           }
  29:       }
  30:     public static void main(String[] args) throws IOException {
  31:         new Server();
  32:       }
  33: //--- Broadcast
  34:     class Broadcast extends Thread {
  35:         public Broadcast() {
  36:           start();
  37:         }
  38:         public void run() {
  39:           while (true) {
  40:               if (!isClear) {
  41:                   String tmp = (String)Message_Array.getFirst();
  42:                   for (int i = 0; i < Threader.size(); i++) {
  43:                       CreateServerThread client = (CreateServerThread)Threader.get(i);
  44:                       client.sendMessage(tmp);
  45:                     }
  46:                   Message_Array.removeFirst();
  47:                   isClear = Message_Array.size() > 0 ? false : true;
  48:                 }
  49:             }
  50:         }
  51:       }
  52: //--- CreateServerThread
  53:     class CreateServerThread extends Thread {
  54:         private Socket client;
  55:         private BufferedReader in;
  56:         private PrintWriter out;
  57:         private String Username;
  58:         public CreateServerThread(Socket s) throws IOException {
  59:             client = s;
  60:             in = new BufferedReader(new InputStreamReader(client.getInputStream()));
  61:             out = new PrintWriter(client.getOutputStream(), true);
  62:             out.println("--- Welcome to this chatroom ---");
  63:             out.println("Input your nickname:");
  64:             start();
  65:           }
  66:         public void sendMessage(String msg) {
  67:           out.println(msg);
  68:         }
  69:         public void run() {
  70:           try {
  71:               int flag = 0;
  72:               Thread_Counter++;
  73:               String line = in.readLine();
  74:               while (!line.equals("bye")) {
  75:                   if (line.equals("l")) {
  76:                       out.println(listOnlineUsers());
  77:                       line = in.readLine();
  78:                       continue;
  79:                     }
  80:                   if (flag++ == 0) {
  81:                       Username = line;
  82:                       User_List.add(Username);
  83:                       out.println(listOnlineUsers());
  84:                       Threader.add(this);
  85:                       pushMessage("[< " + Username + " come on in >]");
  86:                     } else {
  87:                       pushMessage("<" + Username + ">" + line);
  88:                     }
  89:                   line = in.readLine();
  90:                 }
  91:               out.println("--- See you, bye! ---");
  92:               client.close();
  93:             } catch (IOException e) {} finally {
  94:               try {
  95:                   client.close();
  96:                 } catch (IOException e) {}
  97:               Thread_Counter--;
  98:               Threader.remove(this);
  99:               User_List.remove(Username);
 100:               pushMessage("[< " + Username + " left>]");
 101:             }
 102:         }
 103:         private String listOnlineUsers() {
 104:           String s ="-+- Online list -+-\015\012";
 105:           for (int i = 0; i < User_List.size(); i++) {
 106:               s += "[" + User_List.get(i) + "]\015\012";
 107:             }
 108:           s += "-+---------------------+-";
 109:           return s;
 110:         }
 111:         private void pushMessage(String msg) {
 112:           Message_Array.addLast(msg);
 113:           isClear = false;
 114:         }
 115:       }
 116:   }

 

  B6A494567D91378454178B95B7A2D37C

 

这就是程序运行后,多用户登陆并且输入信息后的屏幕。实现了信息的实时广播。用户输入"l"就可以列出在线人员表。

 

 三、整体直观代码块(socket模型)

 

 {客户端socket类}

 

   1: import java.io.*;
   2: import java.net.*;
   3:  
   4: public class NovelClient {
   5:  
   6:     
   7:     private ObjectOutputStream output;
   8:     private ObjectInputStream input;
   9:     private Socket socket;
  10:     private Object o;
  11:     
  12:     
  13:     /**
  14:      * socket流声明
  15:      */
  16:     public NovelClient(){
  17:         try {
  18:             InetAddress addr = InetAddress.getLocalHost();
  19:             String ip=addr.getHostAddress().toString();
  20:             socket=new Socket(ip,8000);
  21:         } catch (UnknownHostException e) {
  22:             e.printStackTrace();
  23:         } catch (IOException e) {
  24:             e.printStackTrace();
  25:         }
  26:     }
  27:  
  28: public Object sendAndRead(Object o){
  29:     try {
  30:         output=new ObjectOutputStream(socket.getOutputStream());
  31:         output.writeObject(o);
  32:         output.flush();
  33:         input=new ObjectInputStream(socket.getInputStream());
  34:         o=(Object) input.readObject();
  35:     } catch (IOException e) {
  36:         e.printStackTrace();
  37:     } catch (ClassNotFoundException e) {
  38:         e.printStackTrace();
  39:     }finally{
  40:           output.close();
  41:           input.close();
  42:     }
  43:     return o;
  44: }

 

{服务器端socket类}

 

   1:  
   2: import java.io.IOException;
   3: import java.net.ServerSocket;
   4: import java.net.Socket;
   5: /**
   6:  * Socket Class
   7:  * @author oracle
   8:  *
   9:  */
  10: public class Server {
  11:  
  12:     private static ServerSocket serversocket;
  13:     private static Socket scoket;
  14:         
  15:     public static void serverStart(){
  16:         try {
  17:             serversocket =new ServerSocket(7566);
  18:             System.out.println("server start...");
  19:             while(true){
  20:                 scoket=serversocket.accept();
  21:                 ServerThread serverthread=new ServerThread(scoket);
  22:                 Thread thread=new Thread(serverthread);
  23:                 thread.start();
  24:             }
  25:         } catch (IOException e) {
  26:             e.printStackTrace();
  27:         }
  28:     }
  29:     
  30:     public static void main(String []args){
  31:         Server.serverStart();
  32:     }
  33:     
  34: }

 

 {服务器端线程类}

 

   1: import java.io.*;
   2: import java.net.Socket;
   3:  
   4: public class ServerThread implements Runnable {
   5:  
   6:     private Socket socket;
   7:     private ObjectInputStream in;
   8:     private ObjectOutputStream out;
   9:     private Objecet o;  
  10:     
  11:     public ServerThread (Socket socket) {
  12:         this.socket=socket;
  13:     }
  14:  
  15:     @Override
  16:     public void run() {
  17:         serverThread();
  18:     }
  19:  
  20:     private void serverThread() {
  21:  
  22:         try {
  23:           in=new ObjectInputStream(socket.getInputStream());
  24:           o=(Object) in.readObject();
  25:  
  26:             out=new ObjectOutputStream(socket.getOutputStream());
  27:             out.writeObject(o);
  28:             out.flush();
  29:         } catch (IOException e) {
  30:             e.printStackTrace();
  31:         } catch (ClassNotFoundException e) {
  32:             e.printStackTrace();
  33:         }        
  34:     }
  35: }

 

声明:最后这个是我自己写的,为了以后理解时候用的。

posted @ 2012-04-05 10:27  levy_host  阅读(4333)  评论(1编辑  收藏  举报