2017-07-24 105 views
2

调查Servlets我创建了一个简单的聊天并在本地IP上进行了测试 - 一切正常。但是当我试图通过真实网络测试它时,连接被拒绝 - java.net.ConnectException: Connection refused: connect。我有动态IP的原因,还是需要额外的设置?提前致谢!我可以使用Java Socket在动态IP上托管聊天服务器吗?

服务器:

/** 
* Created by rnd on 7/4/2017. 
*/ 

import java.io.*; 
import java.net.*; 
import java.nio.charset.Charset; 
import java.nio.charset.StandardCharsets; 
import java.util.*; 

public class VerySimpleChatServer { 

    ArrayList clientOutputStreams; 

    public static void main (String[] args) { 
     new VerySimpleChatServer().go(); 
    } 

    public void go() { 
     clientOutputStreams = new ArrayList(); 
     try { 
      ServerSocket serverSock = new ServerSocket(5000); 

      while(true) { 
       Socket clientSocket = serverSock.accept(); 

       Charset charset = StandardCharsets.UTF_8; 
       OutputStreamWriter osw = new OutputStreamWriter(clientSocket.getOutputStream(), charset); 
       PrintWriter writer = new PrintWriter(new BufferedWriter(osw)); 

//    PrintWriter writer = new PrintWriter(clientSocket.getOutputStream()); 

       writer.println("Welcome to the chat 7 kids.... Семеро Козлят"); 
       writer.flush(); 

       clientOutputStreams.add(writer); 
       Thread t = new Thread(new ClientHandler(clientSocket)); 
       t.start() ; 
       System.out.println("got a connection"); 
      } 
     } catch(Exception ex) { 
      ex.printStackTrace(); 
     } 
    } // Закрываем go 


public class ClientHandler implements Runnable { 

    BufferedReader reader; 
    Socket sock; 

    public ClientHandler(Socket clientSocket) { 

     try { 
      sock = clientSocket; 
      InputStreamReader isReader = new InputStreamReader(sock.getInputStream(), StandardCharsets.UTF_8); 
      reader = new BufferedReader(isReader); 
     } catch(Exception ex) {ex.printStackTrace();} 

    } // Закрываем конструктор 

    public void run() { 
     String message; 

     try { 
      while ((message = reader.readLine()) != null) { 
       System.out.println("read " + message); 
       tellEveryone(message); 
      } // Закрываем while 
     } catch(Exception ex) {ex.printStackTrace();} 
    } // Закрываем run 
} // Закрываем вложенный класс 


    public void tellEveryone(String message) { 
     Iterator it = clientOutputStreams.iterator(); 
     while(it.hasNext()) { 
      try { 
       PrintWriter writer = (PrintWriter) it.next(); 
       writer.println(message); 
       writer.flush(); 
      } catch(Exception ex) { 
       ex.printStackTrace(); 
      } 
     } // Конец цикла while 
    } // Закрываем tellEveryone 

} // Закрываем класс 

客户:

/** 
* Created by rnd on 7/4/2017. 
*/ 

import java.io.*; 
import java.net.*; 
import java.nio.charset.Charset; 
import java.nio.charset.StandardCharsets; 
import java.util.*; 
import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 


public class SimpleChatClient { 

    JTextArea incoming; 
    JTextField outgoing; 
    BufferedReader reader; 
    PrintWriter writer; 
    Socket sock; 

    public static void main(String[] args) { 
     SimpleChatClient client = new SimpleChatClient(); 
     client.go();} 

    public void go(){ 
     JFrame frame = new JFrame("Ludicrously Simple Chat Client"); 
     JPanel mainPanel = new JPanel(); 
     incoming = new JTextArea(15,50); 
     incoming.setLineWrap(true); 
     incoming. setWrapStyleWord (true) ; 
     incoming.setEditable(false); 
     JScrollPane qScroller = new JScrollPane(incoming); 
     qScroller. setVerticalScrollBarPolicy (ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS) ; 
     qScroller. setHorizontalScrollBarPolicy (ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS) ; 
     outgoing = new JTextField(20); 
     JButton sendButton = new JButton("Send") ; 

     sendButton.addActionListener(new SendButtonListener()); 
     mainPanel.add(qScroller); 
     mainPanel.add(outgoing); 
     mainPanel.add(sendButton); 

     setUpNetworking(); 

     Thread readerThread = new Thread(new IncomingReader()); 
     readerThread.start(); 

     frame.getContentPane().add(BorderLayout.CENTER, mainPanel); 
     frame.setSize(800,500); 
     frame.setVisible(true); 

    } 

    private void setUpNetworking() { 
     try { 
      sock = new Socket("178.165.87.221", 5000); 
      InputStreamReader streamReader = new InputStreamReader(sock.getInputStream(), StandardCharsets.UTF_8); 
      reader = new BufferedReader(streamReader); 


      Charset charset = StandardCharsets.UTF_8; 
      OutputStreamWriter osw = new OutputStreamWriter(sock.getOutputStream(), charset); 
      writer = new PrintWriter(new BufferedWriter(osw)); 

//   writer = new PrintWriter(sock.getOutputStream()); 
      System.out.println("networking established"); 
     } catch (IOException ex) { 
       ex.printStackTrace();} 
    } 

    public class SendButtonListener implements ActionListener { 
     public void actionPerformed (ActionEvent ev) { 
      try { 
       writer.println(outgoing.getText()); 
       writer.flush(); 

      } catch(Exception ex) { 
       ex.printStackTrace(); 
      } 
      outgoing. setText ("") ; 
        outgoing.requestFocus() ;} 
    } 

    public class IncomingReader implements Runnable{ 
     @Override 
     public void run() { 
      String message; 

      try{ 
       while((message=reader.readLine())!=null){ 
        System.out.println("read " + message); 
        incoming.append(message + "\n"); 
       } 

      } catch (Exception ex) { 
       ex.printStackTrace(); 
      } 
     } 
    } 

} 

回答

1

如果你真的有一个动态IP,你可以让自己的freedns域(并添加防火墙例外),但最有可能你”重新在NAT后面。为了使它工作,你需要多件事情:

  • 尽管如此,获得freedns域和设置自动IP地址更新
  • 硬编码在客户端
  • 域通过发送UDP数据包露出一组固定的UDP端口无处可去。公共IP上的UDP端口号通常与主机上的端口号相匹配。这部分是最重要的。你可以使用公共的STUN/TURN服务器检查它的工作原理。
  • 将这组端口硬编码到客户端。所以应尽量在freedns域中的所有端口,直到找到一个工作端口
  • 握手包应该有独特的签名为您的聊天使双方都知道他们正在尝试连接到正确的软件

有这个库ice4j用于在NAT后面的两个主机之间建立直接连接,但要开始工作,您仍然需要使用某个通道(电子邮件或其他即时消息传递提供程序)将一个ice4j实例的数据传输到另一个千字节的数据)。

+0

谢谢,但对我来说很复杂。静态IP可以解决这个问题吗?或者我必须执行所有这些操作才能使其工作? – SergeiK

+0

然后按照我的回答的第1段添加防火墙例外。您客户端的IP地址看起来像公共的。 – basin

1

听起来像是防火墙拒绝连接或路由器不是端口转发,所以请求被拒绝。这听起来不像是拥有动态IP的任何事情。

如果您在路由器后面,那么路由器中有设置允许端口转发,您可能需要将规则添加到防火墙。无论如何,只要尝试ping服务器的IP地址就可以进行测试,如果回应那么甚至尝试telnet <server ip> port以查看是否可以连接。

一些事情正在阻碍和拒绝连接!

+0

我试图在外面ping我的IP--它没有被阻塞。当我尝试写入cmd - telnet“我的ip”“我的端口”时,我得到的telnet是一个未知的命令。我使用的是Windows 10 64. – SergeiK

+0

我使用了这个命令netstat -an,并且我没有在打开的端口中找到我使用的端口。我会在晚上尝试在Windows防火墙中添加一个例外。 – SergeiK

+0

是的,我不得不下载“telnet”。这些天它不包含在Windows10中。 1.防火墙(规则)和2.路由器(端口转发)。你不会在另一台机器上看到使用netstat的开放端口,netstat只显示本地机器的信息....祝你好运 –

相关问题