在摆动小程序中使用的套接字

Posted

技术标签:

【中文标题】在摆动小程序中使用的套接字【英文标题】:Socket using in a swing applet 【发布时间】:2011-03-15 17:40:48 【问题描述】:

我应该用 Java 制作一个服务器和客户端,基于 Swing 和 gui。我需要以某种方式制作一个从服务器到客户端以及从客户端到服务器的套接字,并将传递某种字符串。我希望稍后有一个函数可以根据套接字中的字符串做几件事。 出于某种原因,我找不到一个简单的代码示例来说明它是如何以简单的方式完成的。 任何人有任何简单的例子或可以解释它是如何完成的?

【问题讨论】:

【参考方案1】:

基于此example,这是一个使用 Swing 的简单网络客户端-服务器对。注意一些与正确同步相关的问题: GUI 本身是使用invokeLater() 在事件调度线程上构建的。另外,代码依赖append()的线程安全。最后,它结合了文章Text Area Scrolling 中的一个方便提示。

更新:在 Java 7 中,append() 不再被标记为线程安全; invokeLater()display() 中用于对更新进行排序。

package net;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.Scanner;
import javax.swing.*;
import javax.swing.text.DefaultCaret;

/**
 * A simple network client-server pair
 * @http://***.com/questions/3245805
 */
public class Echo implements ActionListener, Runnable 

    private static final String HOST = "127.0.0.1";
    private static final int PORT = 12345;
    private final JFrame f = new JFrame();
    private final JTextField tf = new JTextField(25);
    private final JTextArea ta = new JTextArea(15, 25);
    private final JButton send = new JButton("Send");
    private volatile PrintWriter out;
    private Scanner in;
    private Thread thread;
    private Kind kind;

    public static enum Kind 

        Client(100, "Trying"), Server(500, "Awaiting");
        private int offset;
        private String activity;

        private Kind(int offset, String activity) 
            this.offset = offset;
            this.activity = activity;
        
    

    public Echo(Kind kind) 
        this.kind = kind;
        f.setTitle("Echo " + kind);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getRootPane().setDefaultButton(send);
        f.add(tf, BorderLayout.NORTH);
        f.add(new JScrollPane(ta), BorderLayout.CENTER);
        f.add(send, BorderLayout.SOUTH);
        f.setLocation(kind.offset, 300);
        f.pack();
        send.addActionListener(this);
        ta.setLineWrap(true);
        ta.setWrapStyleWord(true);
        DefaultCaret caret = (DefaultCaret) ta.getCaret();
        caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
        display(kind.activity + HOST + " on port " + PORT);
        thread = new Thread(this, kind.toString());
    

    public void start() 
        f.setVisible(true);
        thread.start();
    

    //@Override
    public void actionPerformed(ActionEvent ae) 
        String s = tf.getText();
        if (out != null) 
            out.println(s);
        
        display(s);
        tf.setText("");
    

    //@Override
    public void run() 
        try 
            Socket socket;
            if (kind == Kind.Client) 
                socket = new Socket(HOST, PORT);
             else 
                ServerSocket ss = new ServerSocket(PORT);
                socket = ss.accept();
            
            in = new Scanner(socket.getInputStream());
            out = new PrintWriter(socket.getOutputStream(), true);
            display("Connected");
            while (true) 
                display(in.nextLine());
            
         catch (Exception e) 
            display(e.getMessage());
            e.printStackTrace(System.err);
        
    

    private void display(final String s) 
        EventQueue.invokeLater(new Runnable() 
            //@Override
            public void run() 
                ta.append(s + "\u23CE\n");
            
        );
    

    public static void main(String[] args) 
        EventQueue.invokeLater(new Runnable() 
            //@Override
            public void run() 
                new Echo(Kind.Server).start();
                new Echo(Kind.Client).start();
            
        );
    

【讨论】:

啊,这提醒了我:这个相关的example 显示了服务器如何接受多个客户端。 我一直在互联网上看到恰好可以工作的代码,因为它使用了恰好是线程安全的 Swing 方法(例如 setText),我找不到一个很好的例子来说明如何让后台网络线程向 EDT 发送事件:/ @Nicolás:我通常使用SwingWorker【参考方案2】:

一个基本的例子是这样的: (基于来自Socket Programming in Java,A.P.Rajshekhar 的教程)

public static void main(String[] args) throws
    UnknownHostException, IOException, InterruptedException 

    Thread serverThread = new Thread(new Runnable() 

        @Override
        public void run() 
            try 
                // create the server socket
                ServerSocket server = new ServerSocket(
                    8888, 5, InetAddress.getLocalHost());
                // wait until clients try to connect
                Socket client = server.accept();

                BufferedReader in = new BufferedReader(new
                    InputStreamReader(client.getInputStream()));

                // loop until the connection is closed
                String line;
                while ((line = in.readLine()) != null) 
                    // output what is received
                    System.out.println(line);
                


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

    Thread clientThread = new Thread(new Runnable() 

        @Override
        public void run() 
            try 
                // connect with the server
                Socket s = new Socket(InetAddress.getLocalHost(), 8888);

                // attach to socket's output stream with auto flush turned on
                PrintWriter out = new PrintWriter(s.getOutputStream(), true);

                // send some text
                out.println("Start");
                out.println("End");
                // close the stream
                out.close();
             catch (Exception e) 
                e.printStackTrace();
            
        
    );

    // start server
    serverThread.start();
    // wait a bit
    Thread.sleep(1000);
    // start client
    clientThread.start();

【讨论】:

但是可以双向传输数据吗?因为ServerSocket没有s.getOutputStream()等客户端所具有的功能,那么它是如何完成的呢?我的意思是我需要就你写的内容进行基本的对话,但是服务器将如何回复他的答案? 一旦建立连接 - 双方是平等的。因此它们可以发送和接收数据

以上是关于在摆动小程序中使用的套接字的主要内容,如果未能解决你的问题,请参考以下文章

地址已在使用中... C 中的套接字

程序突然终止时保持活动的套接字

c_cpp 使用原始套接字发送和接收带有ICMP协议的OUTPUT的数据包的小程序是六进制格式的数据包。可以打印为%c来查看数据。 IP heade

iOS:在套接字中读写(tcp连接)

将 Ajax Web 应用程序迁移到 Web 套接字

作为服务运行时,Windows 不接受套接字连接