简单的Java客户端/服务器程序

20

我正在编写我的第一个Java客户端/服务器程序,它只是与服务器建立连接、发送一个句子,然后服务器将句子全部转为大写并发送回来。这实际上是一本书中的例子,并且当我在同一台机器上运行客户端和服务器,并使用localhost作为服务器地址时,它可以正常运行。但是,当我把客户端程序放在另一台计算机上时,它会超时,并且无法与服务器建立连接。我不确定原因是什么,这有点让人沮丧,因为你的第一个客户端/服务器程序不能在两台不同的计算机上使用。以下是客户端代码:

import java.io.*;
import java.net.*;

public class TCPClient {
    public static void main(String argv[]) throws Exception {
        String sentence;
        String modifiedSentence;
        BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));

        Socket clientSocket = new Socket("localhost", 6789);
        DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
        BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

        sentence = inFromUser.readLine();
        outToServer.writeBytes(sentence + '\n');
        modifiedSentence = inFromServer.readLine();
        System.out.println(modifiedSentence);
        clientSocket.close();
    }
}

以下是服务器端代码:

import java.io.*;
import java.net.*;

public class TCPServer {
    public static void main(String args[]) throws Exception {
        String clientSentence;
        String capitalizedSentence;
        ServerSocket welcomeSocket = new ServerSocket(6789);

        while(true) {
            Socket connectionSocket = welcomeSocket.accept();
            BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
            DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
            clientSentence = inFromClient.readLine();
            capitalizedSentence = clientSentence.toUpperCase() + '\n';
            outToClient.writeBytes(capitalizedSentence);
        }
    }
}

我在两台不同的机器上运行时唯一改变的是客户端程序使用服务器程序所在机器的IP地址来创建套接字(IP地址从whatismyipaddress.com获取)。非常感谢您的帮助。

更新:我确实在校园内,似乎它不允许我使用那个随机端口。有没有关于如何找出可以使用的端口或更有可能被允许的端口的建议?


1
你可以通过这个IP地址连接到服务器吗?(使用ping/telnet/traceroute等工具) - McDowell
在尝试调试程序之前,也许先确保您可以首先ping另一台计算机。这样您就知道网络不是问题所在了。 - user172632
9个回答

8

这可能是防火墙问题。请确保在服务器端将要连接的端口进行端口转发。localhost直接映射到一个IP地址,并通过您的网络堆栈传输。虽然您在代码中更改了一些文本,但程序工作的方式基本相同。


尝试从客户端机器使用telnet <ip> <port>测试与服务器的连接。如果出现“连接被拒绝”或超时,那就是防火墙问题。 - Yoni Roit
1
如果你在学校,几乎肯定有一个路由器。Ping 命令不会有太大帮助;它只能验证机器是否可达,但不能确定端口是否开放。你可以尝试使用浏览器连接远程机器,应该会返回类似于“GET / HTTP 1.1”的信息。或者你可以尝试使用 curl 等工具。 - TMN

3
IP路由的基本概念是:如果您想通过互联网让您的计算机可达,您必须拥有一个唯一的IP地址。这被称为“公共IP地址”。您可以在“www.whatismyipaddress.com”上找到它。如果您的服务器位于某个默认网关后面,则IP数据包将通过该路由器到达您。您的私有IP地址无法从外部世界访问。需要注意的是,只要客户端和服务器的默认网关具有不同的地址,它们的私有IP地址可能相同(这就是IPv4仍然有效的原因)。
我猜您正在尝试从客户端的私有地址ping公共IP地址的服务器(由whatismyipaddress.com提供)。这是不可行的。为了实现这一点,需要进行从私有地址到公共地址的映射,这个过程叫做网络地址转换(NAT)。这在防火墙或路由器中进行配置。
您可以创建自己的私有网络(例如通过wifi)。在这种情况下,由于客户端和服务器将在同一个逻辑网络上,因此不需要进行私有到公共地址的转换,因此您只能使用私有IP地址进行通信。

1

如果你通过外部网站(http://whatismyipaddress.com/)获取了你的IP地址,那么你就拥有了你的外部IP地址。如果你的服务器在同一本地网络中,你可能需要一个内部IP地址。本地IP地址看起来像10.X.X.X、172.X.X.X或192.168.X.X。

尝试这个页面上的建议,查找机器认为自己的IP地址是什么。


(请注意,并非所有的172.X.X.X地址都是本地地址。) - Michael Brewer-Davis
我也从ipconfig中得到了它,而且它是相同的。 - Anton

1

不要使用whatismyipaddress.com的IP地址,而是直接从机器上获取IP地址并插入。whatismyipaddress.com将提供你路由器的地址(假设你在家庭网络上)。我认为端口转发不会起作用,因为你的请求将来自网络内部,而不是外部。


我也执行了ipconfig命令,它给出的地址与whatismyipaddress.com相同。 - Anton
你是在校园网络里吗?他们可能会配置他们的交换机/路由器来阻止某些端口,即使在网络内部也是如此。如果你可以ping通另一台机器而这个不行,那么该端口可能被阻塞了。 - Neal
是的,我在校园里。我猜我应该尝试使用80端口,看看是否有运气? - Anton

0

这是客户端代码

先运行服务器程序,再在另一个命令提示符窗口中运行客户端程序

import java.io.*;
import java.net.*;

public class frmclient 
{
 public static void main(String args[])throws Exception
 {

   try
        {
          DataInputStream d=new DataInputStream(System.in);
          System.out.print("\n1.fact\n2.Sum of digit\nEnter ur choice:");

           int ch=Integer.parseInt(d.readLine());
           System.out.print("\nEnter number:");
           int num=Integer.parseInt(d.readLine());

           Socket s=new Socket("localhost",1024);

           PrintStream ps=new PrintStream(s.getOutputStream());
           ps.println(ch+"");
           ps.println(num+"");

          DataInputStream dis=new DataInputStream(s.getInputStream());
           String response=dis.readLine();
                 System.out.print("Answer:"+response);


                s.close();
        }
        catch(Exception ex)
        {

        }
 }


}

这是服务器端代码

import java.io.*;
import java.net.*;
public class frmserver {

  public static void main(String args[])throws Exception
  {

try
    {

    ServerSocket ss=new ServerSocket(1024);
       System.out.print("\nWaiting for client.....");
       Socket s=ss.accept();
       System.out.print("\nConnected");

       DataInputStream d=new DataInputStream(s.getInputStream());

        int ch=Integer.parseInt(d.readLine());
       int num=Integer.parseInt(d.readLine());
         int result=0;

        PrintStream ps=new PrintStream(s.getOutputStream());
        switch(ch)
        {
          case 1:result=fact(num);
                 ps.println(result);
                  break;
          case 2:result=sum(num);
                 ps.println(result);
                  break;
        }

          ss.close();
          s.close();
    }
catch(Exception ex)
{

}
  }

  public static int fact(int n)
  {
  int ans=1;
    for(int i=n;i>0;i--)
    {
      ans=ans*i;
    }
    return ans;
  }
  public static int sum(int n)
  {
   String str=n+"";
   int ans=0;
    for(int i=0;i<str.length();i++)
    {
      int tmp=Integer.parseInt(str.charAt(i)+"");
      ans=ans+tmp;
    }
    return ans;
  }
}

0

我的尝试编写客户端套接字程序

服务器读取文件并将其打印到控制台,然后将其复制到输出文件

服务器程序:

package SocketProgramming.copy;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerRecieveFile {
    public static void main(String[] args) throws IOException {
        // TODO Auto-enerated method stub
        int filesize = 1022386;
        int bytesRead;
        int currentTot;
        ServerSocket s = new ServerSocket(0);
        int port = s.getLocalPort();
        ServerSocket serverSocket = new ServerSocket(15123);
        while (true) {
            Socket socket = serverSocket.accept();
            byte[] bytearray = new byte[filesize];
            InputStream is = socket.getInputStream();
            File copyFileName = new File("C:/Users/Username/Desktop/Output_file.txt");
            FileOutputStream fos = new FileOutputStream(copyFileName);
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            bytesRead = is.read(bytearray, 0, bytearray.length);
            currentTot = bytesRead;
            do {
                bytesRead = is.read(bytearray, currentTot,
                        (bytearray.length - currentTot));
                if (bytesRead >= 0)
                    currentTot += bytesRead;
            } while (bytesRead > -1);
            bos.write(bytearray, 0, currentTot);
            bos.flush();
            bos.close();
            socket.close();
        }
    }
}

客户端程序:
package SocketProgramming.copy;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

public class ClientSendFile {
    public static void main(String[] args) throws UnknownHostException,
            IOException {
        // final String FILE_NAME="C:/Users/Username/Desktop/Input_file.txt";
        final String FILE_NAME = "C:/Users/Username/Desktop/Input_file.txt";
        ServerSocket s = new ServerSocket(0);
        int port = s.getLocalPort();
        Socket socket = new Socket(InetAddress.getLocalHost(), 15123);
        System.out.println("Accepted connection : " + socket);
        File transferFile = new File(FILE_NAME);
        byte[] bytearray = new byte[(int) transferFile.length()];
        FileInputStream fin = new FileInputStream(transferFile);
        BufferedInputStream bin = new BufferedInputStream(fin);
        bin.read(bytearray, 0, bytearray.length);
        OutputStream os = socket.getOutputStream();
        System.out.println("Sending Files...");

        os.write(bytearray, 0, bytearray.length);

        BufferedReader r = new BufferedReader(new FileReader(FILE_NAME));
        String as = "", line = null;
        while ((line = r.readLine()) != null) {
            as += line + "\n";
            // as += line;

        }
        System.out.print("Input File contains following data: " + as);
        os.flush();
        fin.close();
        bin.close();
        os.close();
        socket.close();

        System.out.println("File transfer complete");
    }
}

2
请不要多次发布您的答案!您可以按下答案下方的编辑按钮以改进它。 - honk

0

你可以从连接的路由器的DHCP列表中获取运行服务器程序的计算机的IP地址。


你能重述一下这个答案以澄清吗?我认为你的意思不是很清楚。 - skrrgwasme
我是指,不要写成 Socket clientSocket = new Socket("localhost", 6789);。这里的 localhost 意味着同一台计算机,所以他需要找到运行服务器的计算机的 IP 地址。如果使用路由器,则可以打开路由器网页查找 DHCP 列表,该列表将显示连接到路由器的设备及其各自的 IP 地址。 - user3417593

0

Outstream没有关闭... 关闭流,以便响应返回给测试客户端。希望这可以帮到您。


-1
import java.io.*;
import java.net.*;
class serversvi1
{
  public static void main(String svi[]) throws IOException
  {
    try
    {
      ServerSocket servsock=new ServerSocket(5510);
      DataInputStream dis=new DataInputStream(System.in);

      System.out.println("enter the file name");

      String fil=dis.readLine();
      System.out.println(fil+" :is file transfer");

      File myfile=new File(fil);
      while(true)
      {
        Socket sock=servsock.accept();
        byte[] mybytearray=new byte[(int)myfile.length()];

        BufferedInputStream bis=new BufferedInputStream(new FileInputStream(myfile));

        bis.read(mybytearray,0,mybytearray.length);

        OutputStream os=sock.getOutputStream();
        os.write(mybytearray,0,mybytearray.length);
        os.flush();

        sock.close();
      }
    }
    catch(Exception saranvi)
    {
      System.out.print(saranvi);
    }
  }
}


import java.io.*;
import java.net.*;

class clientsvi1
{
  public static void main(String svi[])throws IOException
  {
    try
    {
      Socket sock=new Socket("localhost",5510);
      byte[] bytearray=new byte[1024];

      InputStream is=sock.getInputStream();
      DataInputStream dis=new DataInputStream(System.in);
      System.out.println("enter the file name");

      String fil=dis.readLine();
      FileOutputStream fos=new FileOutputStream(fil);
      BufferedOutputStream bos=new  BufferedOutputStream(fos);
      int bytesread=is.read(bytearray,0,bytearray.length);
      bos.write(bytearray,0,bytesread);
      System.out.println("out.txt file is received");
      bos.close();
      sock.close();
    }
    catch(Exception SVI)
    {
      System.out.print(SVI);
    }
  }
}

2
你能解释一下这段代码吗?它对于想要理解正在发生什么或为什么 OP 遇到连接问题的人没有任何帮助。 - Paul Hicks
请添加一些解释。您的答案当前被标记为“低质量”,可能最终会被删除。 - Johannes Jander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接