java的Socket

java API为我们网络通信提供了服务器套接字ServerSocket类和客户端套接字Socket,Socket是网络驱动层提供给应用程序编程的接口和一种机制。
下面提供具体实现例子

服务端--ServerSocket
     ServerSocket类实现了服务器的套接字,主要方法
ServerSocket(int port)-----创建绑定到特定端口的服务器套接字
void setSoTimeout(timeout);----指定超时时间
InetAdress getInetAddress()----返回此服务器套接字的本机地址
Socket accept()--------------侦听并接受此套接字的连接

示例代码:
  1. package com;  
  2.   
  3. import java.io.BufferedInputStream;  
  4. import java.io.BufferedOutputStream;  
  5. import java.io.IOException;  
  6. import java.net.ServerSocket;  
  7. import java.net.Socket;  
  8.   
  9.   
  10. public class Test {  
  11.   
  12.     public static void main(String[] args) {  
  13.           
  14.         try {  
  15.             ServerSocket server=new ServerSocket(8080);  
  16.             //等待客户端连接  
  17.             while(true){  
  18.                 Socket client=server.accept();  
  19.                 //每个客户端建立一个线程  
  20.                 new Thread(new myRunnable(client)).start();;  
  21.             }  
  22.               
  23.         } catch (IOException e) {  
  24.             e.printStackTrace();  
  25.         }  
  26.       
  27.     }  
  28.       
  29. }  
  30.   
  31. class myRunnable implements Runnable{  
  32.       
  33.     private Socket socket;  
  34.       
  35.     public myRunnable(Socket s)  
  36.     {  
  37.         this.socket=s;  
  38.     }  
  39.     //----run方法运行完毕,线程正常结束  
  40.     @Override  
  41.     public void run() {  
  42.           
  43.         try {  
  44.             //接收客户端数据  
  45.             BufferedInputStream is=new BufferedInputStream(socket.getInputStream());              
  46.             int data=is.read()+1;//把客户的数据加一  
  47.               
  48.             Thread.sleep(1000);//休眠一秒  
  49.             //输出到客户端  
  50.             BufferedOutputStream os=new BufferedOutputStream(socket.getOutputStream());           
  51.             os.write(data);//返回数据给客户端  
  52.               
  53.             os.close();       
  54.             os.close();  
  55.                           
  56.         } catch (IOException | InterruptedException e) {  
  57.             e.printStackTrace();  
  58.         }  
  59.           
  60.           
  61.     }  
  62.       
  63. }  
复制代码
客户端----Socket
Socket类实现客户端套接字,套接字是两台机器间通信的端点,主要方法有

Socket(String host,int port)----创建一个套接字将其连接到指定主机的指定端口号
InputStream getInputStream()----返回此套接字的输入流
OutputStream getOutputStream()----返回此套接字的输出流

示例代码:
  1. package com;  
  2.   
  3. import java.io.BufferedInputStream;  
  4. import java.io.BufferedOutputStream;  
  5. import java.io.IOException;  
  6. import java.net.Socket;  
  7. import java.net.UnknownHostException;  
  8.   
  9. public class Client {  
  10.   
  11.     public static void main(String[] args) {  
  12.   
  13.         for(int i=0;i<20;i++)  
  14.         {  
  15.   
  16.             try {  
  17.                 Socket socket = new Socket("localhost", 8080);  
  18.                 //输出到服务器  
  19.                 BufferedOutputStream os=new BufferedOutputStream(socket.getOutputStream());               
  20.                 os.write(i);              
  21.                 os.flush();  
  22.                 //os.close();不能再这里关闭流,关闭流会导致socket也关闭  
  23.   
  24.                 // 构建字符缓冲流  
  25.                 BufferedInputStream is=new BufferedInputStream(socket.getInputStream());  
  26.                   
  27.                 int data=is.read();       
  28.                 is.close();  
  29.                   
  30.                 os.close();  
  31.                   
  32.                 System.out.println(data);             
  33.             } catch (UnknownHostException e) {  
  34.                 e.printStackTrace();  
  35.             } catch (IOException e) {  
  36.                 e.printStackTrace();  
  37.             }  
  38.         }  
  39.           
  40.     }  
  41.   
  42. }  
复制代码
主要不能提前关闭输入输出流,关闭输入输出流会导致Socket关闭


可以引起网络连接关闭的情况有以下4种:

1.直接调用Socket类的close方法。

2.只要Socket类的InputStream和OutputStream有一个关闭,网络连接自动关闭(必须通过调用InputStream和OutputStream的 close方法关闭流,才能使网络可爱接自动关闭)。

3.在程序退出时网络连接自动关闭。
4.将Socket对象设为null或未关闭最使用new Socket(…)建立新对象后,由JVM的垃圾回收器回收为Socket对象分配的内存空间后自动关闭网络连接。

线程池
   在处理多个客户端时是为每一个连接创建一个线程,然而频繁的线程创建会影响性能,所以我们可以使用线程池来解决频线程的创建问题。

线程池:线程池是一种预先创建线程的一种技术。线程池在任务还没到来之前,创建一定数量的线程,放到空闲队列,然后对这些资源进行复用,减少频繁的线程创建和销毁。

        JDK1.5版本后提供了线程池,线程池的顶级接口是Executor,是一个执行工具,线程池的直接接口是ExecutorService,是并发开发中常用的工具类

      要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很清楚的情况下,很有可能配置的线程池不是较优的,因此在Executors类里面提供了一些静态工厂,生成一些常用的线程池。

1. newSingleThreadExecutor

创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

2. newFixedThreadPool

创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。

3. newCachedThreadPool

创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,

那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。

4. newScheduledThreadPool
创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。

此时我们在服务器的用上线程池,使用newFixedThreadPool,代码改为
Java代码  [url=][/url]
  1. package com;  
  2.   
  3. import java.io.BufferedInputStream;  
  4. import java.io.BufferedOutputStream;  
  5. import java.io.IOException;  
  6. import java.net.ServerSocket;  
  7. import java.net.Socket;  
  8.   
  9. import java.util.concurrent.ExecutorService;  
  10. import java.util.concurrent.Executors;  
  11.   
  12.   
  13. public class Test {  
  14.   
  15.     public static void main(String[] args) {  
  16.           
  17.         try {  
  18.             ServerSocket server=new ServerSocket(8080);  
  19.             //获取cpu数  
  20.             int cpu_Num=Runtime.getRuntime().availableProcessors();  
  21.             //创建指定大小的线程池  
  22.             ExecutorService es=Executors.newFixedThreadPool(cpu_Num);  
  23.             //等待客户端连接  
  24.             while(true){  
  25.                 Socket client=server.accept();  
  26.                 //每个客户端建立一个线程  
  27.                 //new Thread(new myRunnable(client)).start();  
  28.                 es.execute(new myRunnable(client));  
  29.             }  
  30.               
  31.         } catch (IOException e) {  
  32.             e.printStackTrace();  
  33.         }  
  34.       
  35.     }  
  36.       
  37. }  
  38.   
  39. class myRunnable implements Runnable{  
  40.       
  41.     private Socket socket;  
  42.       
  43.     public myRunnable(Socket s)  
  44.     {  
  45.         this.socket=s;  
  46.     }  
  47.     //----run方法运行完毕,线程正常结束  
  48.     @Override  
  49.     public void run() {  
  50.           
  51.         try {  
  52.             //接收客户端数据  
  53.             BufferedInputStream is=new BufferedInputStream(socket.getInputStream());              
  54.             int data=is.read()+1;//把客户的数据加一  
  55.               
  56.             Thread.sleep(1000);//休眠一秒  
  57.             //输出到客户端  
  58.             BufferedOutputStream os=new BufferedOutputStream(socket.getOutputStream());           
  59.             os.write(data);//返回数据给客户端  
  60.               
  61.             os.close();       
  62.             os.close();  
  63.                           
  64.         } catch (IOException | InterruptedException e) {  
  65.             e.printStackTrace();  
  66.         }  
  67.           
  68.           
  69.     }  
  70.       
  71. }  
复制代码
这样虽然现实了并发服务器,但这样的服务器效率低,吞吐量低,想提高服务器性能,可以研究学习java的nio和aio,能大大提升服务器性能。
posted @ 2015-05-20 13:46  techfox  阅读(152)  评论(0编辑  收藏  举报