前段时间看完了一本网络编程的书——《TCP/IP》,是用java来讲解的,有个问题一直很困惑不解。就是书里有个例子是讲解聊天室程序的,程序是这样的:服务器端程序收到客户端程序发送过来的信息后,检测所有连接,然后向所有连接发送从客户端收到的信息。在聊天室程序中,客户端发送信息是根据服务器的IP地址来发送的,而服务器是根据已建立的连接来发送信息的。
    那么我想问的是:两个QQ客户端的通信具体是怎么样实现的?两个QQ客户端根据服务器IP地址和服务器建立连接后,第一个QQ客户端将信息发送到服务器后,服务器是怎么样将信息发送到第二个指定的QQ客户端的?根据QQ号码?那又是怎么样实现的?各位高手能不能解释一下,小弟实在想不明白。

解决方案 »

  1.   

    什么叫UDP打洞?你的回答让我更困惑了
      

  2.   

    UDP打洞的意思是两台在不同局域网内的机器通过一些特定的方法建立起UDP连接。这个解释有点复杂,如果你刚刚开始做可以暂时不要考虑。
      

  3.   

    第一个QQ客户端将信息发送到服务器后,服务器是怎么样将信息发送到第二个指定的QQ客户端的、
    ----服务器会维持有所有已登录QQ用户的IP与端口的,所以在这种情况下服务器只要找到第二个指定QQ的IP与端口然后发送数据就可以了。不过QQ实际上会使用直接连接或UDP穿透,可以避免服务器压力太大的。
      

  4.   

    噢,能不能具体解释一下我发的问题?你就说个TCP,当没说!
      

  5.   

    底层都是使用的Java Socket。对于QQ,你可以理解了有一个list,存储了一些QQ号,当一个QQ要与另外的qq聊天的时候,信息发过来,服务器那边就会去查找对应的qq,然后把信息转发出去。我给你看看两边的通讯代码吧:/**  *多线程socket服务端 * @author 49 */ 
    package socketThread; 
    import java.io.BufferedReader; 
    import java.io.IOException; 
    import java.io.InputStream; 
    import java.io.InputStreamReader; 
    import java.io.OutputStream; 
    import java.io.PrintStream; 
    //import java.io.PrintWriter; 
    import java.net.*; 
    import java.util.concurrent.*; 
    import wcdjsrc.dbSocket; 
    import javax.swing.*; public class serverSocket { 
    private int port=10000; 
    private ServerSocket serverSocket; 
    private ExecutorService executorService;//线程池  
    private final int POOL_SIZE=10;//单个CPU线程池大小
      public serverSocket() throws IOException{ 
    serverSocket=new ServerSocket(port); 
    //Runtime的availableProcessor()方法返回当前系统的CPU数目.  executorService=Executors.newFixedThreadPool(
    Runtime.getRuntime().availableProcessors()*POOL_SIZE); 
    System.out.println("服务器启动"); 

    public void service(){ 
    while(true){ 
    Socket socket=null;
     try { 
    //接收客户连接,只要客户进行了连接,就会触发accept();从而建立连接  socket=serverSocket.accept(); 
    executorService.execute(
    new Handler(socket)); 

    catch (Exception e) { 
    e.printStackTrace(); 

    }
     } 
    // public static void main(String[] args) throws IOException { 
    // new serverSocket().service(); 
    // } 
    } class Handler implements Runnable{ 
    private Socket socket; 
    private dbSocket ds=null; 
    public Handler(Socket socket){ 
    this.socket=socket;
     } 
    private PrintStream getWriter(Socket socket) throws IOException{ 
    OutputStream socketOut=socket.getOutputStream(); 
    return new PrintStream(socketOut,true,"UTF-8"); 
    } private BufferedReader getReader(Socket socket) throws IOException{ 
    InputStream socketIn=socket.getInputStream(); 
    return new BufferedReader(new InputStreamReader(socketIn,"UTF-8"));
     } public String echo(String msg){ 
    return "echo:"+msg; 
    } public void run(){ 
    try { 
    System.out.println(
    "New connection accepted "+socket.getInetAddress()+":"+socket.getPort()); BufferedReader br=getReader(socket); 
    PrintStream pw=getWriter(socket); 
    String msg=null; String pwwords=""; 
    while((msg=br.readLine())!=null){ 
    System.out.println(msg);
    //接收到的数据  
    pwwords = "leaderusertrue"; 
    pw.print(pwwords);
    //返回给手机端的数据
    // br.close(); 
    // socket.close();  

    } catch (IOException e) { 
    e.printStackTrace(); 
    }finally{ 
    try { 
    if(socket!=null) 
    socket.close(); 
    } catch (IOException e) { 
    e.printStackTrace(); 
    }
     }
     }
     } 
      

  6.   

    粗略地说
    外网的话就直接用TCP建立连接,连接一旦建立想发就发
    内网的话不能直接建立连接,可以用UDP打洞
    因为内网要访问外网就得跟网关申请端口号
    端口号会有存活时间,中间服务器负责维护这临时端口
    当机子想和另一个内网机子通信 就先跟服务器要端口再建立连接
      

  7.   

    我也做过聊天室程序,不过只是作为j2se练手的
    实际应用中不要研究那么深的,只要知道socket的原来就行了,除非你就想向b/s发展
    ps:我也是菜鸟一个,如果说的不对还请见谅
      

  8.   

    我也不明白楼上讲的什么打洞...在服务器端用一个对象保存已与服务建立链接的客户端,为这个客户端分配一个独立的socket。它客户端发来个信息时,首先这个信息里有这个客户端的QQ号码以及要联系的QQ号码,到服务器时就能找到自己独有的socket。当然另一个客户端也在服务器上有自己独有的socket的,他们通过各自服务器端的socket进行通信(在服务器端进行消息转发)。
      

  9.   

    一开始做聊天的话,应该尝试做最简单的。就是所有客户端直接连接到服务器的特定端口上,并保持长连接。这样服务器就会维持有整个系统中已登录用户与Socket连接的映射。当A向B用户发消息时,A向服务器发送数据包,指定目标为B,消息内容等。
    服务器查找用户B的IP,如果找到就相应的Socket,就可以实现转发了。在自己不熟悉的情况下不要一开始就试图做太复杂的,必须逐步增加功能和改进才是正确的方法