简单的客户端/服务器应用程序交换消息

时间:2014-10-20 22:23:48

标签: java

我的问题是如何在客户端之间交换消息? 如何开发文本消息的方法应该在它们之间交换,直到客户端发送" BYE"或"退出"。 这是服务器的代码

public SocketServer(int port) {
    this.port = port;
}

public void start() throws IOException {
    System.out.println("Starting the socket server at port:" + port);
    serverSocket = new ServerSocket(port);

    //Listen for clients. Block till one connects

    System.out.println("Waiting for clients...");
    Socket client = serverSocket.accept();

    //A client has connected to this server. Send welcome message
    sendWelcomeMessage(client);
}

private void sendWelcomeMessage(Socket client) throws IOException {
    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
    writer.write("Hello. You are connected to a Simple Socket Server. What is your name?");
    writer.flush();       
    writer.close();
}

这对于客户来说

public SocketClient(String hostname, int port){
    this.hostname = hostname;
    this.port = port;
}

public void connect() throws UnknownHostException, IOException{
    System.out.println("Attempting to connect to "+hostname+":"+port);
    socketClient = new Socket(hostname,port);
    System.out.println("Connection Established");
}

public void readResponse() throws IOException{
    String userInput;
    BufferedReader stdIn = new BufferedReader(new InputStreamReader(socketClient.getInputStream()));

    System.out.println("Response from server:");
    while ((userInput = stdIn.readLine()) != null) {
        System.out.println(userInput);
    }
}

2 个答案:

答案 0 :(得分:0)

new ServerSocket(hostname,port)创建一个绑定到'端口的新套接字'并且只能接受新的连接。它不用于数据通信。

当新客户端连接到服务器时,ServerSocket.accept()将返回一个全新的Socket对象,然后用于与客户端通信(可能通过Reader / Writer)。

此时ServerSocket仍然完全有效,再次调用accept()完全独立于新客户端Socket对象的生命周期。

如果再次调用ServerSocket.accept(),它将等待下一个客户端,然后等待下一个等等。

请确保在某个时间点"关闭()"从accept()返回客户端连接。

重要的概念是"阻止"调用。 accept()不允许执行下一行代码,直到新客户端连接。 readLine()不允许执行下一行代码,直到另一方发送了一些数据。

如果要同时启用多个客户端的服务,请创建一个线程池并使用下一个可用线程为新客户端运行协议处理程序。然后"阻止"读/写操作将与线程中的主代码隔离,主代码可以调用" accept()"试。

E.g。对服务器代码的简单扩展将允许它为多个客户端请求提供服务:

System.out.println("Waiting for clients...");
while(!done) {
    final Socket client = serverSocket.accept();

    new Thread() {
    public void run() {
        try {
            sendWelcomeMessage(client);
        } finally {
            client.close();
        }
    }.start();
}

sendWelcomeMessage:
  send welcome
  read input
  if input=="bye" then done=true

可以在Oracle网站上找到与您的代码几乎相同的基本说明和示例:http://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html#later

您还应该阅读有关多线程的优秀教程。试试这个:http://docs.oracle.com/javase/tutorial/essential/concurrency/

答案 1 :(得分:0)

几个月前,我在Netbeans编写了这段代码(APP Chat java)(对我有用),希望对你有帮助。

服务器部分

/**
 * Server
 * @author Zied
 */
public class ChatServer  implements Runnable ,ActionListener{

    private JFrame jfrm;
    private ServerSocket serverSocket;
    private Socket socketClient;
    private  ObjectInputStream ois;
    private  ObjectOutputStream oos;
    private JTextArea  jta;
    private JScrollPane jscrlp;
    private JTextField jtfInput;
    private JButton jbntSend;

    public ChatServer() {

       jfrm=new JFrame("Chat Server");
        jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jfrm.setLayout(new FlowLayout());
        jfrm.setSize(300,320);
        Thread myThread =new Thread(this);
        myThread.start();
        jta= new JTextArea(15, 15);
        jta.setEditable(false);
        jta.setLineWrap(true);
        jscrlp=new JScrollPane(jta);
        jtfInput=new JTextField(15);
        jtfInput.addActionListener(this);
        jbntSend=new JButton("Send");
        jbntSend.addActionListener(this);
        jfrm.getContentPane().add(jscrlp);
        jfrm.getContentPane().add(jbntSend);
        jfrm.getContentPane().add(jtfInput);
        jfrm.setVisible(true);


    }

    /*****   main   ******/
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ChatServer();
            }
        });

    }

    public void actionPerformed(ActionEvent ae)
    {

        if (ae.getActionCommand().equals("Send")|| ae.getSource() instanceof JTextField)
        {
            try {
                oos.writeObject(jtfInput.getText());
                jta.setText(jta.getText()+"You say :"+jtfInput.getText()+"\n");
                jtfInput.setText("");
            } catch (IOException e) {
            }
        }
    }

    public void run() {
       try
       {
           serverSocket = new ServerSocket(4444);
           socketClient =serverSocket.accept();
           String s= String.valueOf( serverSocket.getLocalPort());
           oos=new ObjectOutputStream(socketClient.getOutputStream());
           ois=new ObjectInputStream(socketClient.getInputStream());
           while(true)
           {
               Object input=ois.readObject();
               jta.setText(jta.getText()+"Client says :"+ (String)input +"\n");

               if (input.equals("bye"))
               {
                   System.exit(0);
               }
           }


       }catch(IOException e)
       {
           e.printStackTrace();
       }catch (ClassNotFoundException e)
       {
           e.printStackTrace();

       }
    }
}

客户端部分:

/**
 * Client
 * @author Zied
 */
public class ChatClient  implements Runnable ,ActionListener{

    private JFrame jfrm;
    private Socket socket;
    private  ObjectInputStream ois;
    private  ObjectOutputStream oos;
    private JTextArea  jta;
    private JScrollPane jscrlp;
    private JTextField jtfInput;
    private JButton jbntSend;

    public ChatClient() {

       jfrm=new JFrame("Chat Client");
        jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jfrm.setLayout(new FlowLayout());
        jfrm.setSize(300,320);
        Thread myThread =new Thread(this);
        myThread.start();
        jta= new JTextArea(15, 15);
        jta.setEditable(false);
        jta.setLineWrap(true);
        jscrlp=new JScrollPane(jta);
        jtfInput=new JTextField(15);
        jtfInput.addActionListener(this);
        jbntSend=new JButton("Send");
        jbntSend.addActionListener(this);
        jfrm.getContentPane().add(jscrlp);
        jfrm.getContentPane().add(jbntSend);
        jfrm.getContentPane().add(jtfInput);
        jfrm.setVisible(true);

    }


    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here

          SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ChatClient();
            }
        });
    }

    @Override
    public void run() {
     try
       {
          socket=new Socket("localhost",4444);
           oos=new ObjectOutputStream(socket.getOutputStream());
           ois=new ObjectInputStream(socket.getInputStream());

           while(true)
           {
               Object input=ois.readObject();
               jta.setText(jta.getText()+"Server says :"+ (String)input +"\n");
               if (input.equals("bye"))
               {
                   System.exit(0);
               }
           }


       }catch(IOException e)
       {
           e.printStackTrace();
       }catch (ClassNotFoundException e)
       {
           e.printStackTrace();

       }    }

    @Override
    public void actionPerformed(ActionEvent ae) {

        if (ae.getActionCommand().equals("Send")|| ae.getSource() instanceof JTextField)
        {
            try {
                oos.writeObject(jtfInput.getText());
                jta.setText(jta.getText()+"You say:"+jtfInput.getText()+"\n");
                jtfInput.setText("");
            } catch (IOException e) {
            }
        }
    }

}