java socket实现两个客户段或多个客户端之间通信。大家能够给我一个详细的讲解吗?

解决方案 »

  1.   

    //<<think in java >>的一章1 5 . 2 . 1 一个简单的服务器和客户机程序
    这个例子将以最简单的方式运用套接字对服务器和客户机进行操作。服务器的全部工作就是等候建立一个连
    接,然后用那个连接产生的Socket 创建一个InputStream 以及一个OutputStream。在这之后,它从
    InputStream 读入的所有东西都会反馈给OutputStream,直到接收到行中止(END)为止,最后关闭连接。
    客户机连接与服务器的连接,然后创建一个OutputStream。文本行通过OutputStream 发送。客户机也会创
    建一个InputStream,用它收听服务器说些什么(本例只不过是反馈回来的同样的字句)。
    服务器与客户机(程序)都使用同样的端口号,而且客户机利用本地主机地址连接位于同一台机器中的服务
    540
    器(程序),所以不必在一个物理性的网络里完成测试(在某些配置环境中,可能需要同真正的网络建立连
    接,否则程序不能工作——尽管实际并不通过那个网络通信)。
    下面是服务器程序:
    //: JabberServer.java
    // Very simple server that just
    // echoes whatever the client sends.
    import java.io.*;
    import java.net.*;
    public class JabberServer {
    // Choose a port outside of the range 1-1024:
    public static final int PORT = 8080;
    public static void main(String[] args)
    throws IOException {
    ServerSocket s = new ServerSocket(PORT);
    System.out.println("Started: " + s);
    try {
    // Blocks until a connection occurs:
    Socket socket = s.accept();
    try {
    System.out.println(
    "Connection accepted: "+ socket);
    BufferedReader in =
    new BufferedReader(
    new InputStreamReader(
    socket.getInputStream()));
    // Output is automatically flushed
    // by PrintWriter:
    PrintWriter out =
    new PrintWriter(
    new BufferedWriter(
    new OutputStreamWriter(
    socket.getOutputStream())),true);
    while (true) {
    String str = in.readLine();
    if (str.equals("END")) break;
    System.out.println("Echoing: " + str);
    out.println(str);
    }
    // Always close the two sockets...
    } finally {
    System.out.println("closing...");
    socket.close();
    }
    } finally {
    s.close();
    }
    }
    } ///:~
    可以看到,ServerSocket 需要的只是一个端口编号,不需要IP 地址(因为它就在这台机器上运行)。调用
    541
    accept()时,方法会暂时陷入停顿状态(堵塞),直到某个客户尝试同它建立连接。换言之,尽管它在那里
    等候连接,但其他进程仍能正常运行(参考第14 章)。建好一个连接以后,accept()就会返回一个Socket
    对象,它是那个连接的代表。
    清除套接字的责任在这里得到了很艺术的处理。假如ServerSocket 构建器失败,则程序简单地退出(注意必
    须保证ServerSocket 的构建器在失败之后不会留下任何打开的网络套接字)。针对这种情况,main()会
    “掷”出一个IOException 违例,所以不必使用一个try 块。若ServerSocket 构建器成功执行,则其他所有
    方法调用都必须到一个try-finally 代码块里寻求保护,以确保无论块以什么方式留下,ServerSocket 都能
    正确地关闭。
    同样的道理也适用于由accept()返回的Socket。若accept() 失败,那么我们必须保证Socket 不再存在或者
    含有任何资源,以便不必清除它们。但假若执行成功,则后续的语句必须进入一个try-finally 块内,以保
    障在它们失败的情况下,Socket 仍能得到正确的清除。由于套接字使用了重要的非内存资源,所以在这里必
    须特别谨慎,必须自己动手将它们清除(Java 中没有提供“破坏器”来帮助我们做这件事情)。
    无论ServerSocket 还是由accept()产生的Socket 都打印到System.out 里。这意味着它们的toString方法
    会得到自动调用。这样便产生了:
    ServerSocket[addr=0.0.0.0,PORT=0,localport=8080]
    Socket[addr=127.0.0.1,PORT=1077,localport=8080]
    大家不久就会看到它们如何与客户程序做的事情配合。
    程序的下一部分看来似乎仅仅是打开文件,以便读取和写入,只是InputStream 和OutputStream 是从
    Socket 对象创建的。利用两个“转换器”类InputStreamReader 和OutputStreamWriter ,InputStream 和
    OutputStream 对象已经分别转换成为Java 1.1 的Reader 和Writer 对象。也可以直接使用Java1.0 的
    InputStream 和OutputStream 类,但对输出来说,使用Writer 方式具有明显的优势。这一优势是通过
    PrintWriter 表现出来的,它有一个过载的构建器,能获取第二个参数——一个布尔值标志,指向是否在每
    一次println()结束的时候自动刷新输出(但不适用于print()语句)。每次写入了输出内容后(写进
    out),它的缓冲区必须刷新,使信息能正式通过网络传递出去。对目前这个例子来说,刷新显得尤为重要,
    因为客户和服务器在采取下一步操作之前都要等待一行文本内容的到达。若刷新没有发生,那么信息不会进
    入网络,除非缓冲区满(溢出),这会为本例带来许多问题。
    编写网络应用程序时,需要特别注意自动刷新机制的使用。每次刷新缓冲区时,必须创建和发出一个数据包
    (数据封)。就目前的情况来说,这正是我们所希望的,因为假如包内包含了还没有发出的文本行,服务器
    和客户机之间的相互“握手”就会停止。换句话说,一行的末尾就是一条消息的末尾。但在其他许多情况
    下,消息并不是用行分隔的,所以不如不用自动刷新机制,而用内建的缓冲区判决机制来决定何时发送一个
    数据包。这样一来,我们可以发出较大的数据包,而且处理进程也能加快。
    注意和我们打开的几乎所有数据流一样,它们都要进行缓冲处理。本章末尾有一个练习,清楚展现了假如我
    们不对数据流进行缓冲,那么会得到什么样的后果(速度会变慢)。
    无限while 循环从BufferedReader in 内读取文本行,并将信息写入System.out,然后写入
    PrintWriter.out。注意这可以是任何数据流,它们只是在表面上同网络连接。
    客户程序发出包含了"END"的行后,程序会中止循环,并关闭Socket。
    下面是客户程序的源码:
    //: JabberClient.java
    // Very simple client that just sends
    // lines to the server and reads lines
    // that the server sends.
    import java.net.*;
    import java.io.*;
    public class JabberClient {
    public static void main(String[] args)
    throws IOException {
    // Passing null to getByName() produces the
    // special "Local Loopback" IP address, for
    542
    // testing on one machine w/o a network:
    InetAddress addr =
    InetAddress.getByName(null);
    // Alternatively, you can use
    // the address or name:
    // InetAddress addr =
    // InetAddress.getByName("127.0.0.1");
    // InetAddress addr =
    // InetAddress.getByName("localhost");
    System.out.println("addr = " + addr);
    Socket socket =
    new Socket(addr, JabberServer.PORT);
    // Guard everything in a try-finally to make
    // sure that the socket is closed:
    try {
    System.out.println("socket = " + socket);
    BufferedReader in =
    new BufferedReader(
    new InputStreamReader(
    socket.getInputStream()));
    // Output is automatically flushed
    // by PrintWriter:
    PrintWriter out =
    new PrintWriter(
    new BufferedWriter(
    new OutputStreamWriter(
    socket.getOutputStream())),true);
    for(int i = 0; i < 10; i ++) {
    out.println("howdy " + i);
    String str = in.readLine();
    System.out.println(str);
    }
    out.println("END");
    } finally {
    System.out.println("closing...");
    socket.close();
    }
    }
    } ///:~
    在main()中,大家可看到获得本地主机IP 地址的InetAddress 的三种途径:使用null,使用localhost,
    或者直接使用保留地址127.0.0.1。当然,如果想通过网络同一台远程主机连接,也可以换用那台机器的IP
    地址。打印出InetAddress addr 后(通过对toString()方法的自动调用),结果如下:
    localhost/127.0.0.1
    通过向getByName()传递一个null,它会默认寻找localhost,并生成特殊的保留地址127.0.0.1。注意在名
    为socket 的套接字创建时,同时使用了InetAddress 以及端口号。打印这样的某个Socket 对象时,为了真
    正理解它的含义,请记住一次独一无二的因特网连接是用下述四种数据标识的:clientHost(客户主机)、
    clientPortNumber(客户端口号)、serverHost(服务主机)以及serverPortNumber(服务端口号)。服务
    程序启动后,会在本地主机(127.0.0.1)上建立为它分配的端口(8080)。一旦客户程序发出请求,机器上
    下一个可用的端口就会分配给它(这种情况下是1077),这一行动也在与服务程序相同的机器
    (127.0.0.1)上进行。现在,为了使数据能在客户及服务程序之间来回传送,每一端都需要知道把数据发到
    哪里。所以在同一个“已知”服务程序连接的时候,客户会发出一个“返回地址”,使服务器程序知道将自
    543
    己的数据发到哪儿。我们在服务器端的示范输出中可以体会到这一情况:
    Socket[addr=127.0.0.1,port=1077,localport=8080]
    这意味着服务器刚才已接受了来自127.0.0.1 这台机器的端口1077 的连接,同时监听自己的本地端口
    (8080)。而在客户端:
    Socket[addr=localhost/127.0.0.1,PORT=8080,localport=1077]
    这意味着客户已用自己的本地端口1077 与127.0.0.1 机器上的端口8080 建立了 连接。
    大家会注意到每次重新启动客户程序的时候,本地端口的编号都会增加。这个编号从1025(刚好在系统保留
    的1-1024 之外)开始,并会一直增加下去,除非我们重启机器。若重新启动机器,端口号仍然会从1025 开
    始增值(在Unix 机器中,一旦超过保留的套按字范围,数字就会再次从最小的可用数字开始)。
    创建好Socket 对象后,将其转换成BufferedReader 和PrintWriter 的过程便与在服务器中相同(同样地,
    两种情况下都要从一个Socket 开始)。在这里,客户通过发出字串"howdy",并在后面跟随一个数字,从而
    初始化通信。注意缓冲区必须再次刷新(这是自动发生的,通过传递给PrintWriter 构建器的第二个参
    数)。若缓冲区没有刷新,那么整个会话(通信)都会被挂起,因为用于初始化的“howdy”永远不会发送出
    去(缓冲区不够满,不足以造成发送动作的自动进行)。从服务器返回的每一行都会写入System.out,以验
    证一切都在正常运转。为中止会话,需要发出一个"END"。若客户程序简单地挂起,那么服务器会“掷”出一
    个违例。
    大家在这里可以看到我们采用了同样的措施来确保由Socket 代表的网络资源得到正确的清除,这是用一个
    try-finally 块实现的。
    套接字建立了一个“专用”连接,它会一直持续到明确断开连接为止(专用连接也可能间接性地断开,前提
    是某一端或者中间的某条链路出现故障而崩溃)。这意味着参与连接的双方都被锁定在通信中,而且无论是
    否有数据传递,连接都会连续处于开放状态。从表面看,这似乎是一种合理的连网方式。然而,它也为网络
    带来了额外的开销。本章后面会介绍进行连网的另一种方式。采用那种方式,连接的建立只是暂时的
      

  2.   

    2.如何开发一个Server-Client模型的程序
    开发原理:
    服务器,使用ServerSocket监听指定的端口,端口可以随意指定(由于1024以下的端口通常属于保留端口,在一些操作系统中不可以随意使用,所以建议使用大于1024的端口),等待客户连接请求,客户连接后,会话产生;在完成会话后,关闭连接。
    客户端,使用Socket对网络上某一个服务器的某一个端口发出连接请求,一旦连接成功,打开会话;会话完成后,关闭Socket。客户端不需要指定打开的端口,通常临时的、动态的分配一个1024以上的端口。
    {建立服务器}import java.net.*;
    import java.io.*;
    public class Server
    {
    private ServerSocket ss;
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;
    public Server()
    {
    try
    {
    ss = new ServerSocket(10000);
    while (true)
    {
    socket = ss.accept();
    in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    out = new PrintWriter(socket.getOutputStream(),true);
    String line = in.readLine();
    out.println("you input is :" + line);
    out.close();
    in.close();
    socket.close();
    }
    ss.close();
    }
    catch (IOException e)
    {}
    }
    public static void main(String[] args)
    {
    new Server();
    }
    }
    这个程序建立了一个服务器,它一直监听10000端口,等待用户连接。在建立连接后给客户端返回一段信息,然后结束会话。这个程序一次只能接受一个客户连接。
    {建立客户端}import java.io.*;
    import java.net.*;
    public class Client
    {
    Socket socket;
    BufferedReader in;
    PrintWriter out;
    public Client()
    {
    try
    {
    socket = new Socket("xxx.xxx.xxx.xxx", 10000);
    in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    out = new PrintWriter(socket.getOutputStream(),true);
    BufferedReader line = new BufferedReader(new InputStreamReader(System.in));
    out.println(line.readLine());
    line.close();
    out.close();
    in.close();
    socket.close();
    }
    catch (IOException e)
    {}
    }
    public static void main(String[] args)
    {
    new Client();
    }
    }
    这个客户端连接到地址为xxx.xxx.xxx.xxx的服务器,端口为10000,并从键盘输入一行信息,发送到服务器,然后接受服务器的返回信息,最后结束会话。
    第二步 多个客户同时连接
    在实际的网络环境里,同一时间只对一个用户服务是不可行的。一个优秀的网络服务程序除了能处理用户的输入信息,还必须能够同时响应多个客户端的连接请求。在java中,实现以上功能特点是非常容易的。
    设计原理:
    主程序监听一端口,等待客户接入;同时构造一个线程类,准备接管会话。当一个Socket会话产生后,将这个会话交给线程处理,然后主程序继续监听。运用Thread类或Runnable接口来实现是不错的办法。
    {实现消息共享}import java.io.*;
    import java.net.*;
    public class Server extends ServerSocket
    {
    private static final int SERVER_PORT = 10000;
    public Server() throws IOException
    {
    super(SERVER_PORT);
    try
    {
    while (true)
    {
    Socket socket = accept();
    new CreateServerThread(socket);
    }
    }
    catch (IOException e)
    {}
    finally
    {
    close();
    }
    }
    //--- CreateServerThread
    class CreateServerThread extends Thread
    {
    private Socket client;
    private BufferedReader in;
    private PrintWriter out;
    public CreateServerThread(Socket s) throws IOException
    {
    client = s;
    in = new BufferedReader(new InputStreamReader(client.getInputStream(), "GB2312"));
    out = new PrintWriter(client.getOutputStream(), true);
    out.println("--- Welcome ---");
    start();
    }
    public void run()
    {
    try
    {
    String line = in.readLine();
    while (!line.equals("bye"))
    {
    String msg = createMessage(line);
    out.println(msg);
    line = in.readLine();
    }
    out.println("--- See you, bye! ---");
    client.close();
    }
    catch (IOException e)
    {}
    }
    private String createMessage(String line)
    {
    xxxxxxxxx;
    }
    }
    public static void main(String[] args) throws IOException
    {
    new Server();
    }
    }
    这个程序监听10000端口,并将接入交给CreateServerThread线程运行。CreateServerThread线程接受输入,并将输入回应客户,直到客户输入"bye",线程结束。我们可以在createMessage方法中,对输入进行处理,并产生结果,然后把结果返回给客户。
      

  3.   

    为了方便的支持套接字网络开发,java.net包中专门提供了用来支持套接字网络开发的socket和serversocket类:
    (1)服务器首先启动监听程序,对指定的端口进行监听,等待接收客户端的连接请求。
    (2)客户端程序启动,请求连接服务器的指定端口。
    (3)服务器收到客户端的连接请求后与客户端建立套接字连接。
    (4)连接成功后,客户端与服务器分别打开两个流,其中客户端的输入流连接到服务器的输出流,服务器的输入流
    连接到客户端的输出流,两边的流建立连接后就可以双向的通信了。
    (5)当通信完毕后客户端与服务器端两边各自断开连接。
      

  4.   

    import java.net.*; 
    import java.io.*; 
    public class Server 

    private ServerSocket ss; 
    private Socket socket; 
    private BufferedReader in; 
    private PrintWriter out; 
    public Server() 

    try 

    ss = new ServerSocket(10000); 
    while (true) 

    socket = ss.accept(); 
    in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
    out = new PrintWriter(socket.getOutputStream(),true); 
    String line = in.readLine(); 
    out.println("you input is :" + line); 
    out.close(); 
    in.close(); 
    socket.close(); 

    ss.close(); //为什么这里无法访问

    catch (IOException e) 
    {} 

    public static void main(String[] args) 

    new Server(); 


    Server.java:26: 无法访问的语句
    ss.close();
    ^
    1 错误
      

  5.   

    上面各位大概说了下,但是小弟还是不太明白谁有没具体的程序啊,发到我邮箱嘛  [email protected]
      

  6.   

    你还没有登录社区!用户名 密 码登录 有效期  浏览器进程 永久 一个月一天 一小时 页面登录注册 找回密码首 页 文 章 博 客 论 坛 下 载 图 书 炎黄盈动   专题文章 博客 资源下载 图书推荐 相册搜索 当前位置:中文JAVA技术网 >> 专题文章 >> Java基础 >> 查看专题文章 
    关于Java Socket编程的详细介绍
    阅读次数: 810次 发布时间: 2008-04-23 09:31:09发布人: 沃尔夫
    来源: csai 事实上网络编程简单的理解就是两台计算机相互通讯数据而已.对于程序员而言,去掌握一种编程接口并使用一种编程模型相对就会显得简单的多了。Java SDK提供一些相对简单的Api来完成这些工作。Socket就是其中之一。对于Java而言,这些Api存在与java.net 这个包里面。因此只要导入这个包就可以准备网络编程了。   网络编程的基本模型就是客户机到服务器模型。简单的说就是两个进程之间相互通讯,然后其中一个必须提供一个固定的位置,而另一个则只需要知道这个固定的位置,并去建立两者之间的联系。然后完成数据的通讯就可以了。这里提供固定位置的通常称为服务器,而建立联系的通常叫做客户端。基于这个简单的模型,就可以进入网络编程啦。
      Java对这个模型的支持有很多种Api。而这里我只想介绍有关Socket的编程接口。对于Java而言已经简化了Socket的编程接口。首先我们来讨论有关提供固定位置的服务方是如何建立的。Java提供了ServerSocket来对其进行支持,事实上当你创建该类的一个实力对象并提供一个端口资源你就建立了一个固定位置可以让其他计算机来访问你。ServerSocket server=new ServerSocket(6789);这里稍微要注意的是端口的分配必须是唯一的。因为端口是为了唯一标识每台计算机唯一服务的。另外端口号是从0~65535之间的,前1024个端口已经被Tcp/Ip 作为保留端口,因此你所分配的端口只能是1024个之后的。好了,我们有了固定位置.现在所需要的就是一根连接线了。该连接线由客户方首先提出要求。因此Java同样提供了一个Socket对象来对其进行支持。只要客户方创建一个Socket的实例对象进行支持就可以了。Socket client=new Socket(InetAddress.getLocalHost(),5678);客户机必须知道有关服务器的IP地址。对于着一点Java也提供了一个相关的类InetAddress。该对象的实例必须通过它的静态方法来提供。它的静态方法主要提供了得到本机IP 和通过名字或IP直接得到InetAddress的方法。
      好了.上面的方法基本可以建立一条连线让两台计算机相互交流了。可是数据是如何传输的呢?事实上I/O操作总是和网络编程息息相关的。因为底层的网络是继续数据的,除非远程调用,处理问题的核心在执行上。否则数据的交互还是依赖于IO操作的.所以你也必须导入java.io这个包。java的IO操作也不复杂,它提供了针对于字节流和Unicode的读者和写者,然后也提供了一个缓冲用于数据的读写。
      BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream()));  PrintWriter out=new PrintWriter(server.getOutputStream());
      上面两句就是建立缓冲并把原始的字节流转变为Unicode可以操作。而原始的字节流来源于Socket的两个方法。getInputStream()和getOutputStream()方。分别用来得到输入和输出。那么现在有了基本的模型和基本的操作工具。我们可以做一个简单的Socket例程了。
      服务方:
      import java.io.*;  import java.net.*;  public class MyServer {  public static void main(String[] args) throws IOException{  ServerSocket server=new ServerSocket(5678);  Socket client=server.accept();  BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));  PrintWriter out=new PrintWriter(client.getOutputStream());  while(true){  String str=in.readLine();  System.out.println(str);  out.println("has receive....");  out.flush();  if(str.equals("end"))  break;  }  client.close();  }  }
      这个程序的主要目的在于服务器不断接收客户机所写入的信息只到。客户机发送"End"字符串就退出程序。并且服务器也会做出"Receive"为回应。告知客户机已接收到消息。
      客户机代码:
      import java.net.*;  import java.io.*;  public class Client{  static Socket server;  public static void main(String[] args)throws Exception{  server=new Socket(InetAddress.getLocalHost(),5678);  BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream()));  PrintWriter out=new PrintWriter(server.getOutputStream());  BufferedReader wt=new BufferedReader(new InputStreamReader(System.in));  while(true){  String str=wt.readLine();  out.println(str);  out.flush();  if(str.equals("end")){  break;  }  System.out.println(in.readLine());  }  server.close();  }  }
      客户机代码则是接受客户键盘输入,并把该信息输出,然后输出"End"用来做退出标识。
            这个程序只是简单的两台计算机之间的通讯。如果是多个客户同时访问一个服务器呢?你可以试着再运行一个客户端,结果是会抛出异常的。那么多个客户端如何实现呢?
      其实,简单的分析一下,就可以看出客户和服务通讯的主要通道就是Socket本身。而服务器通过accept方法就是同意和客户建立通讯。这样当客户建立Socket的同时。服务器也会使用这一根连线来先后通讯。那么既然如此只要我们存在多条连线就可以了。那么我们的程序可以变为如下:
      服务器:
      import java.io.*;  import java.net.*;  public class MyServer {  public static void main(String[] args) throws IOException{  ServerSocket server=new ServerSocket(5678);  while(true){  Socket client=server.accept();  BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));  PrintWriter out=new PrintWriter(client.getOutputStream());  while(true){  String str=in.readLine();  System.out.println(str);  out.println("has receive....");  out.flush();  if(str.equals("end"))  break;  }  client.close();  }  }  }
      这里仅仅只是加了一个外层的While循环。这个循环的目的就是当一个客户进来就为它分配一个Socket直到这个客户完成一次和服务器的交互,这里也就是接受到客户的"End"消息。那么现在就实现了多客户之间的交互了。但是问题又来了。这样做虽然解决了多客户,可是是排队执行的。也就是说当一个客户和服务器完成一次通讯之后下一个客户才可以进来和服务器交互,无法做到同时服务。那么要如何才能同时达到既能相互之间交流又能同时交流呢?很显然这是一个并行执行的问题了。所以线程是最好的解决方案。
      那么下面的问题是如何使用线程.首先要做的事情是创建线程并使得其可以和网络连线取得联系,然后由线程来执行刚才的操作,要创建线程要么直接继承Thread要么实现Runnable接口,要建立和Socket的联系只要传递引用就可以了,而要执行线程就必须重写run方法。而run方法所做的事情.就是刚才单线程版本main所做的事情。因此我们的程序变成了这样:
      import java.net.*;  import java.io.*;  public class MultiUser extends Thread{  private Socket client;  public MultiUser(Socket c){  this.client=c;  }  public void run(){  try{  BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));  PrintWriter out=new PrintWriter(client.getOutputStream());  //Mutil User but can't parallel  while(true){  String str=in.readLine();  System.out.println(str);  out.println("has receive....");  out.flush();  if(str.equals("end"))  break;  }  client.close();  }catch(IOException ex){  }finally{  }  }  public static void main(String[] args)throws IOException{  ServerSocket server=new ServerSocket(5678);  while(true){  //transfer location change Single User or Multi User  MultiUser mu=new MultiUser(server.accept());  mu.start();  }  }  }
      我的类直接从Thread类继承了下来。并且通过构造函数传递引用和客户Socket建立了联系。这样每个线程就有了一个通讯管道,同样我们可以填写run方法,把之前的操作交给线程来完成。这样多客户并行的Socket就建立起来了。
     -5 -3 -1 - +1 +3 +5  
    评分:0
    我来说两句内容:发表评论 相关文章• [IDE工具/测试工具] Eclipse使用简介   浏览:38  发表日期[09-05-06] • [SOA/ESB/JMS] SOA主要目标是业务与IT之间保持一致   浏览:5  发表日期[09-05-06] • [Java基础] Java编译器中对string对象的优化   浏览:15  发表日期[09-05-06] • [Java基础] 浅谈Java 同步机制   浏览:36  发表日期[09-05-05] • [业界新闻] 开源专家布兰肯霍恩:甲骨文将后悔收购Sun   浏览:34  发表日期[09-05-05] • [业界新闻] MDA技术BPM理念亮相建设行业企业信息化应用发展研讨会(图)   浏览:17  发表日期[09-05-05] • [业界新闻] SaaS成09软博会关注重点 论坛凸显四大亮点   浏览:11  发表日期[09-05-05] • [数据库持久层] Mysql 添加用户的两种方法   浏览:32  发表日期[09-05-05] • [业界新闻] G&B:“甲型H1N1”西班牙语木马病毒惊现网络   浏览:28  发表日期[09-05-05] • [开源框架] Java开源缓存平台Terracotta 3.0版本发布   浏览:27  发表日期[09-05-05] • [业界新闻] 防范“猪流感”在网络世界传播 警惕垃圾邮件   浏览:18  发表日期[09-05-04] • [实用技巧] 一位软件测试工程师2个月面试总结   浏览:178  发表日期[09-05-04] 技术专栏+-专题技术
    --多线程编程 --Socket/RMI --Ajax --应用服务器 --WebService/EAI --J2EE --Servlet/JSP --Applet/Swing/SWT --数据库持久层 --JavaMail --J2ME/WAP/智能卡 --Java认证考试 --设计模式 --团队管理 --开源框架 --SOA/ESB/JMS +-新手入门 --业界新闻 --Java基础 --实用技巧 --IDE工具/测试工具 --XML 参与讨论 Web开发
    (JSP/Servlet/JSF/Tapestry/Spring/..)  
     Java入门基础
    (环境/安装/语法/调试/编译/执行/..)  
     数据库开发
    (JDBC/JDO/Hibernate/EJB3/..)  
     Java高级编程
    (多线程/IO/算法/设计模式/网络/..)  
     Ajax框架
    (Flex/Prototype/dojo/YUI/DWR/EXT/..)  
     开发工具
    (Eclipse/NetBeans/IDEA/...)  
     UI客户端开发
    (Eclipse插件开发/Applet/Swing/..)  
     J2EE服务器
    (Tomcat/JBoss/WebLogic/WebSphere/..)  
     资源共享
    (图书/视频/项目/代码/..)  
     集成架构
    (/SOA/ESB/EAI/OSGi/SCA/SDO/..)  
     畅谈W3C,共同学习CSS  
     综合问题
    (性能/压力/测试/JVM/安全/集群/..)  
     找茬寻宝
    (正在进行中......)  
     J2ME移动受限设备开发  
     开源技术讨论  
    CN-JAVA在线翻译
      
    详细解释 专业解释 简单解释   
    关于CN-JAVA | 广告服务 | 联系方式 | 友情链接 | 网站地图 | 版权声明 | 网站统计  
    CopyRight(C) 2001-2008 Jackliu AT炎黄盈动. All Rights Reserved. 京ICP备05051608号 Actionsoft Co., Ltd Tel:010-62962320/2343/3450 Fax: 010-62961851 
      

  7.   

    听上去 很像是种局域网的应用
    如果这样,首先的任务则是获得每个客户端列表
    将这个客户端程序都做一个TCP或UDP端口的监听
    在客户端在线时,根据所在的网域进行一轮的扫描
    去尝试连接监听的端口,连接上并确定是另一个客户端则加进来
    可定时进行扫描,而保证有新客户端加入
    这样每个客户端列表则有了
    通讯就不用多说了,上面的例子写得很详细
    这种方式我也是在一个局域网文件传输的工具里发现的如果是种广局网的应用,最好开发一个服务器端的小程序将监听的端口暴露在外网
    能让外网能访问到;而这个程序的作用则是记录每个访问的客户端IP地址和端口
    建议采用UDP协议;即可很方便的实现P2P的通讯方式,而无需服务端终转
    过程:  一客户端登录,先去访问服务器端的小程序;告诉服务器端我在线
    服务器将客户端IP和端口记录下来;然后服务器将其它所有客户端在线列表发回给客户端
    这样 客户端有了其它客户端的IP和端口;即可各客户端的访问注意的是  这种方式最好采用UDP协议,既可解决不同网域之间的访问
    因为A客户端只要向服务端发送了数据;既将一个内网的路由器进行了一次NAT穿透
    这样所有客户端都可以访问到这个A客户端了
    这个UDP的穿透时间好像是30秒还是45秒来着,如果超过这个时间路由器将会释放这个NAT穿透的SESSION
    所以最好能定时发送心跳包给服务器端;这样以来服务器端也可做一个会话来判断这个客户端是否在线
    TCP的穿透时间则更长,但需要特殊手段才能打通;这种TCP的穿透 网上也有相关的控件和源代码
      

  8.   

    20楼的那个错误是因为程序会一直执行while(true)中的内容知道程序结束,所以永远也不会执行那句的!
      

  9.   

    ss.close();放到finally{..}中即可。