Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 643|回复: 0

Java Socket构建阻塞的TCP通信

[复制链接]

该用户从未签到

发表于 2011-9-13 14:17:41 | 显示全部楼层 |阅读模式
[blockquote]/*300*250,创建于2011-2-24*/ var cpro_id = 'u388789';
-
[/blockquote]1.服务器端
1.创建ServerSocket对象,可在构造子中指定监听的端口;

privateintport = 8000;
private ServerSocket serverSocket;
……
serverSocket = new ServerSocket(port);


2.服务器端调用ServerSocket对象的accept()方法,该方法一直监听端口,等待客户的连接请求,如果接收到一个连接请求,accept()方法就会返回一个Socket对象,这个Socket对象与客户端的Socket对象将形成一条通信线路;
Socket socket = null;
socket = serverSocket.accept(); // 等待客户连接


3.Socket类提供了getInputStream()方法和getOutputStream()方法。
InputStream socketIn = socket.getInputStream();
OutputStream socketOut = socket.getOutputStream();

源代码EchoServer.java
publicclass EchoServer {
    privateintport = 8000;
    private ServerSocket serverSocket;
    public EchoServer() throws IOException {
       serverSocket = new ServerSocket(port);
       System.out.println("Server Start");
    }
    public String echo(String msg) {
       return"echo:" + msg;
    }
    private PrintWriter getWriter(Socket socket) throws IOException {
       OutputStream socketOut = socket.getOutputStream();
       returnnew PrintWriter(socketOut, true);
    }
    private BufferedReader getReader(Socket socket) throws IOException {
       InputStream socketIn = socket.getInputStream();
       returnnew BufferedReader(new InputStreamReader(socketIn));
    }
    publicvoid service() {
       while (true) {
           Socket socket = null;
           try {
              socket = serverSocket.accept(); // 等待客户连接
              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));
                  if (msg.equals("bye")) // 如果客户发送的消息为“bye”,就结束通信
                     break;
              }
           } catch (IOException e) {
              e.printStackTrace();
           } finally {
              try {
                  if (socket != null)
                     socket.close(); // 断开连接
              } catch (IOException e) {
                  e.printStackTrace();
              }
           }
       }
    }
    publicstaticvoid main(String args[]) throws IOException {
       new EchoServer().service();
    }
}


2.客户端
1.创建一个Socket对象,指定服务器端的地址和端口;
private String host = "localhost";
privateintport = 8000;
private Socket socket;
……
socket = new Socket(host, port);


这里作为客户端,它的端口是由操作系统随机产生的。

2.Socket类提供了getInputStream()方法和getOutputStream()方法。
InputStream socketIn = socket.getInputStream();
OutputStream socketOut = socket.getOutputStream();


源代码EchoClient.java
publicclass EchoClient {
    private String host = "localhost";
    privateintport = 8000;
    private Socket socket;
    public EchoClient() throws IOException {
       socket = new Socket(host, port);
    }
    publicstaticvoid main(String args[]) throws IOException {
       new EchoClient().talk();
    }
    private PrintWriter getWriter(Socket socket) throws IOException {
       OutputStream socketOut = socket.getOutputStream();
       returnnew PrintWriter(socketOut, true);
    }
    private BufferedReader getReader(Socket socket) throws IOException {
       InputStream socketIn = socket.getInputStream();
       returnnew BufferedReader(new InputStreamReader(socketIn));
    }
    publicvoid talk() throws IOException {
       try {
           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"))
                  break;
           }
       } catch (IOException e) {
           e.printStackTrace();
       } finally {
           try {
              socket.close();
           } catch (IOException e) {
              e.printStackTrace();
           }
       }
    }
}


3.关闭Socket
1.关闭Socket的代码;
try {
       ……
    } catch (IOException e) {
       e.printStackTrace();
    } finally {
       try {
           socket.close();
       } catch (IOException e) {
           e.printStackTrace();
       }
    }


Socket类提供3个状态测试方法。
-isClosed():如果Socket已经连接到远程主机,并且还没有关闭,则返回true;
-isConnected():如果Socket曾经连接到远程主机,则返回true;
-isBound():如果Socket已经与一个本地端口绑定,则返回true。

判断一个Socket对象当前是否处于连接状态,
Boolean isConnected = socket.isConnected() && !socket.isClosed();

2.处理关闭
(1)当进程A与进程B交换的是字符流,并且是一行一行地读写数据时,可以事先约定一个特殊的标志。
BufferedReader br = getReader(socket);
PrintWriter pw = getWriter(socket);
String msg = null;
while ((msg = br.readLine()) != null) {
    System.out.println(msg);
    pw.println(echo(msg));
    if (msg.equals("bye")) // 如果客户发送的消息为“bye”,就结束通信
       break;
}


(2)进程A先发送一个消息,告诉进程B所发送的正文长度,然后发送正文。进程B只要读取完该长度的数据就可以停止读数据。

(3)进程A发送完所有数据后,关闭Socket。当进程B读入进程A发送的所有数据后,再次执行输入流的read()方法时,该方法返回-1.
InputStream socketIn = socket.getInputStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
byte[] buff = newbyte[1024];
int len = -1;
while ((len = socketIn.read(buff)) != -1) {
    buffer.write(buff, 0, len);
}
System.out.println(new String(buffer.toByteArray()));


(4)当调用Socket的close()方法关闭Socket时,它的输入流和输出流都被关闭。如果仅仅希望关闭输入或输出流其中之一,可调用半关闭方法:shutdownInput()和shutdownOutput()。先后调用Socket的shutdownInput()和shutdownOutput()方法,仅仅关闭输入流和输出流,并不等价于调用close()方法。在通信结束后仍然需要调用close()方法,因为该方法才会释放Socket占用的资源。

4.多线程服务器
EchoServer只能顺序的处理Client端的请求,这里使用ExecutorService指定一个线程池用于处理连接请求。
private ExecutorService executorService; // 线程池
privatefinalintPOOL_SIZE = 4; // 单个CPU时线程池中工作线程的数目
…….
executorService = Executors.newFixedThreadPool(Runtime.getRuntime()
              .availableProcessors()* POOL_SIZE);
……
try {
       socket = serverSocket.accept();
       executorService.execute(new Handler(socket));
    } catch (IOException e) {
       e.printStackTrace();
    }



Hander类封装了原来处理连接请求的逻辑,只要当前线程池中有空闲的线程,就可以用于处理请求。


源代码MultiEchoServer.java
publicclass MultiEchoServer {
    privateintport = 8000;
    private ServerSocket serverSocket;
    private ExecutorService executorService; // 线程池
    privatefinalintPOOL_SIZE = 4; // 单个CPU时线程池中工作线程的数目
    public MultiEchoServer() throws IOException {
       serverSocket = new ServerSocket(port);
       executorService = Executors.newFixedThreadPool(Runtime.getRuntime()
              .availableProcessors()
              * POOL_SIZE);
       System.out.println("Server Start");
    }
    publicvoid service() {
       while (true) {
           Socket socket = null;
           try {
              socket = serverSocket.accept();
              executorService.execute(new Handler(socket));
           } catch (IOException e) {
              e.printStackTrace();
           }
       }
    }
    publicstaticvoid main(String args[]) throws IOException {
       new MultiEchoServer().service();
    }
}
class Handler implements Runnable {
    private Socket socket;
    public Handler(Socket socket) {
       this.socket = socket;
    }
    private PrintWriter getWriter(Socket socket) throws IOException {
       OutputStream socketOut = socket.getOutputStream();
       returnnew PrintWriter(socketOut, true);
    }
    private BufferedReader getReader(Socket socket) throws IOException {
       InputStream socketIn = socket.getInputStream();
       returnnew BufferedReader(new InputStreamReader(socketIn));
    }
    public String echo(String msg) {
       return"echo:" + msg;
    }
    publicvoid run() {
       try {
           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));
              if (msg.equals("bye"))
                  break;
           }
       } catch (IOException e) {
           e.printStackTrace();
       } finally {
           try {
              if (socket != null)
                  socket.close();
           } catch (IOException e) {
              e.printStackTrace();
           }
       }
    }
}

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2024-5-5 08:33 , Processed in 0.442034 second(s), 46 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表