socket通信 _ 一个简单的群聊系统

群聊系统要用到通信socket协议,在java中要用到两个类java.net.ServerSocket和

Java.net.Socket.ServerSocket用于创建服务器,而Socket用于创建连接。

简单介绍Socket通信的用法

首先,我们建立一个简单的 “服务器—客户端”一对一的连接来说明如何用socket通信。

1.建立一个服务器ServerSocket  server=new ServerSocket(port);

Port是一个整形数据,表示端口号,端口的范围是0~65534,而0~1024端口是系统预留端口,为避免端口被占用我们可以选择一个较大的数:int port=9900;

2.建立一个链接来连接服务器和客户端。

服务器:Socket socket_server=server.accept();这是一个死等函数,若没有成功建立连接,则程序不会向下执行。

客户端:Socket socket_client=new Socket(IPaddr,port);IPaddr表示你的网络IP地址,本系统在本机上运行可以用127.0.0.1代替,否则可以在命令行下输入ipconfig进行查找。Port为服务器建立的端口号。

3.完成这些以后我们就可以进行服务器和客户端之间的通信了。

发消息需要用到java.io.DataInputStream和java.io.DataOutputStream。

 在发送端:DataOutputStream dout=new DataOutputStream(socket_sever.getoutputString);

               dout.writeUTF(massage);

 接收端:DateInputStream din=new DateInputStream(socket_client.getInputStream);

               String accept=din.readUTF();

这样,服务器端和客户端就可以进行简单的通信了。当然,若想时时刻刻都能接收到信息,则必须把接受代码放入线程中让其循环执行。

 

群聊系统的设计:

服务器:

功能描述:创建一个服务器,接收来自客户端的消息,并分发给每个客户端。

1.建立服务器

public void BuildServer() {
        try {
            int port=9900;
            server = new ServerSocket(port);
            System.out.println("创建群聊服务器成功!");
            InetAddress addr=InetAddress.getLocalHost();
            System.out.println("本机地址:"+addr); //将网络地址和端口打印方便客户端进行连接
            System.out.println("端口号:"+port);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2.创建socket,由于客户端不止一个,故socket也不只一个,我们可以将Socket=server.accept();循环执行。

    @Override   //这是重写Thread类中的run();
    public void run() {
        while (true) {
            try {
                Socket socket = server.accept();
//链接建立后,接收客户端传来的用户名信息 DataInputStream in
= new DataInputStream( socket.getInputStream()); String name=in.readUTF(); if (name.equals("")) name="匿名用户"; System.out.println(name + "已成功连接!"); try { DataOutputStream out = new DataOutputStream(socket.getOutputStream()); out.writeUTF(("亲爱的"+name+",你已连接到服务器!\n\r")); } catch (IOException e) { e.printStackTrace(); }
//这是一个线程类,之后将会创建,用于与客户端收发消息 GroupThread gt
= new GroupThread(socket, list, name);
//list是一个链表,存储每个已存在的连接,其初始化:ArrayList<GroupThread> list = new ArrayList<GroupThread>(); list.add(gt); gt.start(); }
catch (IOException e) { } }

3.主函数

public class GroupServer extends Thread {
    /**
     * @param 群聊服务器
     */
    ServerSocket server;
    ArrayList<GroupThread> list = new ArrayList<GroupThread>();

    public void BuildServer() {
    }
    @Override
    public void run() {
    }

    public static void main(String[] args) {
        GroupServer s = new GroupServer();
        s.BuildServer();
        s.start();
    }

}

 

4.GroupThread类,用于服务器与客户端的收发信息,收到来自客户端的信息后分发出去。

public class GroupThread extends Thread{
    Socket socket;
    String str;
    String accept;
    ArrayList<GroupThread> list;
    private String username;
    public  GroupThread(Socket socket, ArrayList<GroupThread> list,String name){
        this.socket=socket;
        this.list=list;
        this.username=name;
    }
    
   @SuppressWarnings("deprecation")
public void run(){
       while (true) {
           try {
            DataInputStream in = new DataInputStream(
                    socket.getInputStream());
            accept=in.readUTF();
            if(!accept.equals("")){sendGroup();
            }
        } catch (IOException e) {
            try {
//客户端关闭后断开连接,将这个链接从链表中移除,并停止线程 System.out.println(username
+"已断开连接!"); list.remove(list.indexOf(this));this.stop(); socket.close(); } catch (IOException e1) { System.out.println("断开连接出现异常!"); } } } } private void sendGroup() { int index=list.indexOf(this); for(int i=0;i<list.size();i++){ if(index!=i){ list.get(i).Send(accept); } }
public void Send(String str){
        try {
            DataOutputStream out = new DataOutputStream(
                    socket.getOutputStream());
            out.writeUTF(str);
        } catch (IOException e) {
            e.printStackTrace();
        }
    } }

 客户端:

1.登陆界面,提取登录名(未做验证),用于显示群聊过程中的昵称

public class Login extends JFrame {
    private static final long serialVersionUID = 1L;
    private JTextField name = new JTextField(9);
    private JButton login = new JButton("登录");
    public void showUI() {
        this.setTitle("请输入你的用户名");
        this.setSize(300, 240);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.setLayout(new FlowLayout());
        this.setResizable(false);
        this.add(new JLabel("用户名:"));
        this.add(name);
        Listener listener=new Listener(this,name);
        name.addKeyListener(listener);
        this.add(login);
        login.setFocusable(false);
        login.addActionListener(listener);
        this.setVisible(true);
    }
    public static void main(String[] args) {
        new Login().showUI();
    }
}

class Listener implements KeyListener,ActionListener{
    Login login;JTextField jt;
    private String name;
    public Listener(Login login,JTextField jt){
        this.jt=jt;
        this.login=login;
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        name=jt.getText();
        MyChat chat=new MyChat(name);
        try {
            chat.runit();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        login.setVisible(false);
    }
    @Override
    public void keyTyped(KeyEvent e) {
    }
    @Override
    public void keyPressed(KeyEvent e) {
    }
    @Override
    public void keyReleased(KeyEvent e) {
        if(e.getKeyCode()==10){
            name=jt.getText();
            MyChat chat=new MyChat(name);
            try {
                chat.runit();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            login.setVisible(false);
        }
    }

}

2.聊天界面

public class MyChat extends Thread {
    JButton send = new JButton("发送");
    JTextField jt = new JTextField(20);
    JTextArea jta = new JTextArea();
    DataOutputStream out;
    Socket socket;
    String str;
    byte secret=19;
    String name;
    ServerSocket server;
    JFrame thiss = new JFrame();
    public MyChat(String name){
        this.name=name;
    }
    public void client() throws IOException {
        thiss.setSize(400, 300);
        thiss.setLayout(new BorderLayout());
        thiss.setDefaultCloseOperation(3);
        thiss.setLocationRelativeTo(null);
        JScrollPane js = new JScrollPane(jta);
        thiss.getContentPane().add(js);
        thiss.setResizable(false);
        JPanel south = new JPanel();
        thiss.add(south, BorderLayout.SOUTH);
        south.add(jt);
        send.setFocusable(false);
        jta.setFocusable(false);
        jt.addKeyListener(new KeyListener() {
            @Override
            public void keyTyped(KeyEvent e) {
            }
            @Override
            public void keyReleased(KeyEvent e) {
            }
            @Override
            public void keyPressed(KeyEvent e) {
                if (KeyEvent.getKeyText(e.getKeyCode()).equals("Enter")) {
                    str = jt.getText() + "\n\r";
                    jt.setText("");
                    jta.append(name +":" + str);
                    try {
                        out = new DataOutputStream(socket.getOutputStream());
                    out.writeUTF(name +":" + str);
                    } catch (IOException e1) {
                    }
                }
                ;
            }
        });
        send.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                str = jt.getText() + "\n\r";
                jt.setText("");
                jta.append(name+":" + str);
                try {
                    out = new DataOutputStream(socket.getOutputStream());
                    out.writeUTF((name + ":" + str));
                } catch (IOException e) {
                }
            }
        });
        south.add(send);
        thiss.setVisible(true);
    }
    @SuppressWarnings("deprecation")
    public void run() {
        while (true) {
            try {
                DataInputStream in = new DataInputStream(
                        socket.getInputStream());
                String accept = in.readUTF();
                if(!accept.equals(""))jta.append(accept);
            } catch (IOException e) {
                try {
                    System.out.println("连接已断开!");
                    socket.close();
                    this.stop();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            } 
        }
    }
    public void connect() {
        try {
            String addr="127.0.0.1";//本机地址
            socket = new Socket(addr, 9900);
            out = new DataOutputStream(socket.getOutputStream());
            out.writeUTF(name);
            thiss.setTitle(name);
        } catch (IOException e) {
        }
    }
    public void runit() throws IOException{
        this.client();
        this.connect();
        this.start();
        if(name.equals("")){name="匿名";
        thiss.setTitle("匿名");}
    }
}

运行结果:

posted @ 2015-07-29 20:12  浔阳楚狂  阅读(543)  评论(0编辑  收藏  举报