Socket套接字理解——Java语言实现多人聊天应用程序

Socket套接字

所谓socket 通常也称作”套接字“,用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过”套接字”向网络发出请求或者应答网络请求。

Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。

重要的Socket API:

java.net.Socket继承于java.lang.Object,有八个构造器,其方法并不多,下面介绍使用最频繁的三个方法,其它方法大家可以见JDK-1.3文档。

. Accept方法用于产生”阻塞”,直到接受到一个连接,并且返回一个客户端的Socket对象实例。”阻塞”是一个术语,它使程序运行暂时”停留”在这个地方,直到一个会话产生,然后程序继续;通常”阻塞”是由循环产生的。

. getInputStream方法获得网络连接输入,同时返回一个InputStream对象实例。
. getOutputStream方法连接的另一端将得到输入,同时返回一个OutputStream对象实例。

注意:其中getInputStream和getOutputStream方法均会产生一个IOException,它必须被捕获,因为它们返回的流对象,通常都会被另一个流对象使用。

此处参考文献原地址

多人聊天实现

服务器端代码

  1. ChatServer.java
import java.io.*;
import java.util.*;
import java.net.*;

public class ChatServer {
    boolean started = false;
    ServerSocket ss = null;

    List<Client> clients = new ArrayList<Client>();

    public static void main(String Args[]) {

        new ChatServer().start();

    }

    public void start() {
        try {
            ss = new ServerSocket(8888); // Tcp的端口
            started = true;
        } catch (BindException e) {
            System.out.println("this port is already used");
            System.out.println("自动关掉程序");
            System.exit(0);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {

            while (started) {
                Socket s = ss.accept();
                Client c = new Client(s);

                System.out.println("a client connected!");
                new Thread(c).start();
                clients.add(c);
                // dis.close();

            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                ss.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    }

    class Client implements Runnable {
        private Socket s;
        private DataInputStream dis = null;
        private boolean bConnected = false;
        private DataOutputStream dos = null;

        public Client(Socket s) {
            this.s = s;
            try {
                dis = new DataInputStream(s.getInputStream());
                dos = new DataOutputStream(s.getOutputStream());
                bConnected = true;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        public void send(String str) {
            try {
                dos.writeUTF(str);
            } catch (IOException e) {
                clients.remove(this);
                System.out.println("对方退出了,我从list里面去掉了!");
                //e.printStackTrace();
            }
        }

        public void run() {
            try {
                while (bConnected) {

                    String str = dis.readUTF();
System.out.println(str);
                    for(int i=0;i<clients.size();i++){
                        Client c = clients.get(i);
                        c.send(str);
                    }

                }
            } catch (EOFException e) {
                System.out.println("closed client");
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                try {
                    if (dis != null)
                        dis.close();
                    if (s != null)
                        s.close();
                    if(dos != null)
                        dos.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        }

    }
}

客户端代码

  1. ChatClient.java
import java.awt.*;
import java.net.*;
import java.awt.event.*;
import java.io.*;

public class ChatClient extends Frame {
    Socket s = null;
    DataOutputStream dos;
    DataInputStream dis;
    private boolean bConnected= false;
    TextField tfTxt = new TextField();
    TextArea taContent = new TextArea();

    Thread tRecv = new Thread(new RecvThread());

    public static void main(String[] args) {

        new ChatClient().launchFrame();
    }

    public void launchFrame() {
        setLocation(400, 300);
        this.setSize(300, 300);
        add(tfTxt, BorderLayout.SOUTH);
        add(taContent, BorderLayout.NORTH);
        pack();
        this.addWindowListener(new WindowAdapter(){

            @Override
            public void windowClosing(WindowEvent e) {
                disconnect();
                System.exit(0);

            }
        });
        tfTxt.addActionListener(new TFListener());
        setVisible(true);
        connect();
        tRecv.start();
    }

    public void connect(){
        try{
        s = new Socket("127.0.0.1",8888);
        dos = new DataOutputStream(s.getOutputStream());
        dis = new DataInputStream(s.getInputStream());
System.out.println("Connected");
        bConnected = true;

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

    public void disconnect(){
        try {
            bConnected = false;
        //  tRecv.join();

    //  } catch(InterruptedException e){
    //      e.printStackTrace();
        }
        finally{

            try {
                dos.close();
                dis.close();
                s.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

    }

    private class TFListener implements ActionListener{


        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub
            String str = tfTxt.getText().trim();
            //taContent.setText(str);
            tfTxt.setText("");

            try{
            //DataOutputStream dos = new DataOutputStream(s.getOutputStream());
            dos.writeUTF(str);
            //dos.flush();
            //dos.close();
            }catch(IOException e1){
                e1.printStackTrace();

            }
        }


    }

    private class RecvThread implements Runnable{

        public void run(){
        while(bConnected){
            try {
                String str = dis.readUTF();
                taContent.setText(taContent.getText()+str+'\n');
            } catch(SocketException e){
                System.out.println("退出了,bye!");
            }
            catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }   

        }
    }

}

运行结果演示

  • 第一个客户端起来
    这里写图片描述
  • 第二个客户端起来

这里写图片描述
- 第三个客户端

这里写图片描述


猜你喜欢

转载自blog.csdn.net/siying8419/article/details/79735901