步步测试完善Java中Socket通信图解法(三)
来源:互联网 发布:国泰安数据库账号 编辑:程序博客网 时间:2024/05/17 17:16
步步测试完善Java中Socket通信图解法(一)
http://blog.csdn.net/llhhyy1989/article/details/8471725
步步测试完善Java中Socket通信图解法(二)
http://blog.csdn.net/llhhyy1989/article/details/8479626
步步测试完善Java中Socket通信图解法(三)
http://blog.csdn.net/llhhyy1989/article/details/8503955
---------------------------------------------------------------------------------------------------------------------------------------
http://blog.csdn.net/llhhyy1989/article/details/8503955
步步测试完善Java中Socket通信图解法(三)
分类: j2SE 2013-01-15 09:37 582人阅读 评论(3)收藏举报
javasocket
目录
简介
Java中Socket通信简介
单线程一对一服务器1——>1客户端
单线程一对一服务器1<——>1客户端
多线程一对多服务器1<——>N客户端【非聊天室的服务器通过用户输入发送数据】
多线程一对多服务器1<——>N客户端【聊天室】
多线程最终服务器和客户端集成一体【swing程序】
【多线程】一对多服务器1<——>N客户端(非聊天室的服务器通过用户输入发送数据)
对,解决方案,就是发送数据和接受数据不在同一个进程,这样,这两个进程互不影响。
解决方案如下:服务器端和客户端如下:
当然,若下文要考虑,多个客户端连接同一个服务端时,所以,应该对每个sockt连接开启一个线程。但是对于客户端而言,只要把发送和接受分离即可。所以在客户端中,可以把发送数据和主进程放在一块。如下图:
代码实现如下:
服务器端:
[java] view plaincopyprint?
- package com17.tcp;
- import java.io.IOException;
- import java.net.ServerSocket;
- import java.net.Socket;
- public class MyServer {
- public static void main(String[] args) {
- try {
- ServerSocket ss=new ServerSocket(30000);
- while(true)
- {
- //此行代码会阻塞,将一直等待别人的连接
- Socket s=ss.accept();
- if(s.isConnected())
- {
- System.out.println("一个客户端连接此服务器"+s.getInetAddress());
- }
- //每当客户端连接后启动一条ServerThread线程为该客户端服务
- new Thread( new ServerThread(s)).start();
- //发送数据到客户端
- new Thread(new ServerThread2(s)).start();
- }
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
package com17.tcp;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;public class MyServer { public static void main(String[] args) { try { ServerSocket ss=new ServerSocket(30000); while(true) { //此行代码会阻塞,将一直等待别人的连接 Socket s=ss.accept(); if(s.isConnected()) { System.out.println("一个客户端连接此服务器"+s.getInetAddress()); } //每当客户端连接后启动一条ServerThread线程为该客户端服务 new Thread( new ServerThread(s)).start(); //发送数据到客户端 new Thread(new ServerThread2(s)).start(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}
接受数据的并打印的线程:
[html] view plaincopyprint?
- package com17.tcp;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.io.PrintStream;
- import java.net.Socket;
- import java.util.Scanner;
- public class ServerThread implements Runnable {
- //定义当前线程所处理的socket
- Socket s=null;
- //该线程所处理的socket所对应的输入流
- BufferedReader br=null;
- public ServerThread(Socket s)
- {
- try
- {
- this.s=s;
- //初始化socket对应的输入流
- br=new BufferedReader(new InputStreamReader(s.getInputStream()));
- }
- catch(IOException e)
- {
- e.printStackTrace();
- }
- }
- @Override
- public void run() {
- try
- {
- String content=null;
- //采用循环不断从Socket中读取客户端发送过来的数据
- while((content=readFromClient())!=null)
- {
- System.out.println("来自客户端消息:"+content);
- }
- System.out.println("消息:"+content);
- PrintStream ps=new PrintStream(s.getOutputStream());
- ps.println(br.readLine());
- }catch(Exception e)
- {
- try
- {
- s.close();
- }catch(IOException ex)
- {
- ex.printStackTrace();
- }
- }
- }
- //定义读取客户端数据的方法
- private String readFromClient()
- {
- try
- {
- return br.readLine();
- }
- //如果捕捉到异常,表明该socket对应的客户端已经关闭
- catch(IOException e)
- {
- e.printStackTrace();
- }
- return null;
- }
- }
package com17.tcp;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.net.Socket;import java.util.Scanner;public class ServerThread implements Runnable { //定义当前线程所处理的socket Socket s=null; //该线程所处理的socket所对应的输入流 BufferedReader br=null; public ServerThread(Socket s) { try { this.s=s; //初始化socket对应的输入流 br=new BufferedReader(new InputStreamReader(s.getInputStream())); } catch(IOException e) { e.printStackTrace(); } } @Override public void run() { try { String content=null; //采用循环不断从Socket中读取客户端发送过来的数据 while((content=readFromClient())!=null) { System.out.println("来自客户端消息:"+content); } System.out.println("消息:"+content); PrintStream ps=new PrintStream(s.getOutputStream()); ps.println(br.readLine()); }catch(Exception e) { try { s.close(); }catch(IOException ex) { ex.printStackTrace(); } } } //定义读取客户端数据的方法 private String readFromClient() { try { return br.readLine(); } //如果捕捉到异常,表明该socket对应的客户端已经关闭 catch(IOException e) { e.printStackTrace(); } return null; }}
发送数据到客户端的线程:
[html] view plaincopyprint?
- package com17.tcp;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.io.PrintStream;
- import java.net.Socket;
- public class ServerThread2 implements Runnable {
- private Socket s;
- //用来处理发送数据的
- private PrintStream ps=null;
- public ServerThread2(Socket s)
- {
- try
- {
- this.s=s;
- ps=new PrintStream(s.getOutputStream());
- }
- catch(IOException e)
- {
- try
- {
- s.close();
- }
- catch(IOException ex)
- {
- ex.printStackTrace();
- }
- }
- }
- @Override
- public void run() {
- try
- {
- //发送数据到客户端
- String line=null;
- //不断读取键盘的输入
- BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
- while((line=br.readLine())!=null)
- {
- //将用户的键盘输入内容写入socket对应的输出流
- ps.println(line);
- }
- }
- catch(IOException e)
- {
- e.printStackTrace();
- }
- }
- }
package com17.tcp;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.net.Socket;public class ServerThread2 implements Runnable { private Socket s; //用来处理发送数据的 private PrintStream ps=null; public ServerThread2(Socket s) { try { this.s=s; ps=new PrintStream(s.getOutputStream()); } catch(IOException e) { try { s.close(); } catch(IOException ex) { ex.printStackTrace(); } } } @Override public void run() { try { //发送数据到客户端 String line=null; //不断读取键盘的输入 BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); while((line=br.readLine())!=null) { //将用户的键盘输入内容写入socket对应的输出流 ps.println(line); } } catch(IOException e) { e.printStackTrace(); } }}
效果如下:
但是我们通过以上的代码,要实现这种如下:
虽然上述代码中使用了多线程,每个客户端请求,都会产生一个读线程和写线程。但是也不能完成上图的要求。
为什么呢?
主要在于写的线程。
因为写的线程,虽然捕捉了发送的socket套接字,但是写线程中是时刻监听用户输入System.in。
这样,当多个客户端连接服务器端时,则服务器端有多个线程监听用户输入System.in。但是令人头疼的是,服务器端只有一个dos窗口,而不像客户端一个dos窗口监听一个用户输入System.in。
访问中服务器端结果如下:
所以服务器想通过用户输入形式发送给多个客户端,这种形式是不可行的。
代码中,永远只能发给具有活动的线程。结果不是你想象的那样,发给你想象的线程。
当然,若是服务器不是通过监听用户输入则当然可以实现上述的要求的
我们改一下服务器端:不通过监听用户输入。
服务器端中,接受线程中,一接受到客户的数据,则发送数据。
服务器端,线程如图:
接受线程中修改上述的demo
[html] view plaincopyprint?
- //采用循环不断从Socket中读取客户端发送过来的数据
- while((content=readFromClient ())!=null )
- {
- System. out.println( "来自客户端消息:" +content);
- ps.println( "客户端"+s.getInetAddress()+"消息已经收入到,消息为:" +content);
- }
//采用循环不断从Socket中读取客户端发送过来的数据 while((content=readFromClient ())!=null ) { System. out.println( "来自客户端消息:" +content); ps.println( "客户端"+s.getInetAddress()+"消息已经收入到,消息为:" +content); }
效果图如下:
【多线程】一对多服务器1<——>N客户端(聊天室)
我想通过上述几个例子,想必对通信的方式已经了解,并且也掌握通信的原理以及通信方法。
那我们再说,聊天室通信,就是类似我们qq群。一人发表了看法,则其他的人都能看到此消息。
猜想qq实现方式,就是通过服务器转发【仅此个人看法】
那我们这个例子实现方式如下图:
那这个例子 不在贴代码,我们说一下思路,在服务器端有个列表,专门用来保存客户端的socket。只要客户端连接服务器,就把客户端的socket添加到服务器列表中。当接受到任何客户端数据时,就把数据转发给列表中任何一个客户端socket。
部分代码如下:
[html] view plaincopyprint?
- //采用循环不断从Socket中读取客户端发送过来的数据
- while((content=readFromClient())!= null)
- {
- //便利socketList中的每一个socket
- //将读到的内容向每个socket发送一次
- for(Socket s:MyServer. socketList)
- {
- PrintStream ps= new PrintStream(s.getOutputStream());
- ps.println(content);
- }
- }
- 步步测试完善Java中Socket通信图解法(三)
- 步步测试完善Java中Socket通信图解法(三)
- 步步测试完善Java中Socket通信图解法(一)
- 步步测试完善Java中Socket通信图解法(二)
- 步步测试完善Java中Socket通信图解法(一)
- 步步测试完善Java中Socket通信图解法(二)
- 步步测试完善Java中Socket通信图解法(四) .
- Java finally步步完善
- Java Socket 通信 (三)
- Java 中 Socket 通信
- java中socket通信
- Java中Socket通信
- 三种onClick事件与Java中Socket通信简介
- 敏捷测试与最佳实践(三) 敏捷测试(翻译完善中)
- java学习小笔记(三.socket通信)
- Java Socket学习(三)——客户端之间通信
- socket通信基础(三)
- Socket网络通信(三)
- 菜鸟:IOS 学习:磨难记 (第二天)
- SqlDataReader和SqlDataAdapter+DataSet 区别
- Android_launcher的源码详细分析
- 怎么选择运放
- 这几天学习总结
- 步步测试完善Java中Socket通信图解法(三)
- 遇到的问题java
- 优秀的WEB开发人员应该知道的10件事
- Web前端性能优化经验分享
- Android 4.0 Launcher源码分析系列(一)
- Android 4.0 Launcher源码分析系列(二)
- NYOJ - 我排第几个
- Sybase ASE及其它产品的license获取与生成
- 一个前端工程师眼里的NodeJS