Java套接字的端口问题

时间:2013-05-29 13:50:53

标签: java sockets

我首先使用线程和套接字,所以我正在尝试聊天(本地)

ClientA(实际上是服务器):

public class ClientA {

    public static void main(String[] args) {

        ServerSocket servsock = null;
        try {
            servsock = new ServerSocket(9998);
            Socket conn = servsock.accept();
            System.out.println("server socket listening on local port : " + servsock.getLocalPort());
            System.out.println("socket listening on local port : " + conn.getLocalPort());
            System.out.println("socket listening on port : " + conn.getPort());
            servsock.close();

            TReadingSock tls = new TReadingSock(conn);
            tls.start();
            TWritingSock tes = new TWritingSock(conn);
            tes.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客户B,实际客户:

public class ClientB {

    public static void main(String[] args) {

        Socket sock = null;
        try {
            sock = new Socket("localhost", 9998);
            System.out.println("socket listening on local port : " + sock.getLocalPort());
            System.out.println("socket listening on port : " + sock.getPort());
        } catch (IOException e) {
            e.printStackTrace();
        }

        TReadingSock tls = new TReadingSock(sock);
        tls.start();
        TWritingSock tes = new TWritingSock(sock);
        tes.start();
    }
}

印刷品显示:

客户A:

server socket listening on local port : 9998
socket listening on local port : 9998 
socket listening on port : 50875

客户B:

socket listening on local port : 50875  
socket listening on port : 9998

所以,就像它看起来一样愚蠢,我在理解整个套接字时遇到了严重的问题,我唯一得到的是我的程序正在监听不同的端口,我不明白为什么。我想这对某些人来说显得非常明显,所以我请求你的帮助来启发我!

提前致谢。

编辑:谢谢你的所有答案。问题是,对我来说,你需要一个ServerSocket来监听端口并接受任何尝试连接的客户端。当它完成后,它返回一个Socket对象,我将它传递给我的线程,以便他们可以完成自己的工作。这是针对ClientA的。客户端B只创建一个Socket,它将尝试连接到9998端口,这是我用我的ServerSocket监听的端口。然后将它传递给它的线程。问题是,当我启动我的客户端(A然后B),并且我在控制台A中写入时,控制台B上没有任何反应(也许我应该早些指定,抱歉)。

我猜这是由于我的套接字正在使用的端口。我检查了几个教程,即使在阅读了你的回复之后,我也没有看到什么是错的,所以要么我错过了一些非常明显的概念,要么它不是连接本身,而是我处理连接的方式。为了以防万一,我将发布线程的内容:

public class TWritingSock extends Thread {
    private Socket sockw;

    public TWritingSock(Socket sockw){
        this.sockw = sockw;
    }

    @Override
    public void run(){
        try {
            while(true){
                //Recuperation des saisies clavier
                BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

                //Ecriture de la saisie
                PrintWriter pw= new PrintWriter(sockw.getOutputStream(), true);

                String typed = br.readLine();
                if(typed.equals("fin")){
                    //sockw.close();
                    System.out.println("fermé");
                    break;
                }
                pw.write(typed);
            }           
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                sockw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    } 
}

public class TReadingSock extends Thread {
    private Socket sockr;

    public TReadingSock(Socket sockr){
        this.sockr = sockr;
    }

    @Override
    public void run(){
        try {
            while(true){
                BufferedReader br = new BufferedReader(new InputStreamReader(sockr.getInputStream()));
                String typed = br.readLine();
                if(typed.equals("fin")){
                    //sockr.close();
                    System.out.println("fermé");
                    break;
                }
                System.out.println(typed);
            }   
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                sockr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3 个答案:

答案 0 :(得分:2)

(我将使用原始和简单的图像来讨论Socket,请将其视为我尝试尽可能简单地解释它。)

将Socket视为隧道。现在,如果我告诉你隧道的末端是9998,你就可以到达它,但是这条隧道的终点可以是任何东西,由你决定。

ClientA(实际上是服务器),正在说“我想收听端口9998”。当ClientA连接“Ok我们已连接时,我在端口9998上,而你在50875上。”。

ClientB说“我想要到达您的端口9998,我将使用我的端口50875这样做。”

两个应用程序现在都可以通过隧道进行通信,因为它们知道它的去向。

答案 1 :(得分:1)

Internet上的每个TCP连接由两对或四个元素组成:端点A IP地址,端点A端口号和端点B IP地址,端点B端口。在传输级别,地址在IP packet header中指定,而端口在TCP header中注明。这允许明确识别主机和进程(通过端口)来传送数据包。

当您bind()监听“服务器”套接字时,您可以修复该端点端口号(在您的情况下为9998)。当客户端连接到达时,其他三个部分也是固定的 - 您的本地IP是连接到达的网络接口,远程IP和端口是连接客户端,其中端口通常由操作系统从您的示例中的ephemeral ports池,50875。

答案 2 :(得分:0)

好的,让我试着让你理解这些概念很简单。因此,当您阅读本教程时,它将是有意义的。

套接字是非常简单的术语,是客户端和服务器之间的隧道。当一个人读,另一个人写。换句话说,当一个人等待阅读时,另一个人写入隧道。当读取成功时,接收器可以处理数据。

这里客户端和服务器都可以进行双向通信。有些人创建一个Z字形的模式,服务器等待读取,客户端发送数据并进入读取等待,服务器处理它并响应客户端。客户端显示成功/错误。等等。

在他们进行读写之前,他们会形成一个连接。为了形成连接,他们需要告诉对方他们的身份(IP地址/ DNS)是什么。

到目前为止?

如果您需要我解释端口,请告诉我。