java的Socket

时间:2015-05-20 18:50:16   收藏:0   阅读:181

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,能大大提升服务器性能。


原文:http://wufanxin.blog.51cto.com/7318130/1653129

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!