最基础的java socket聊天程序应该烂熟于心

过年在家有大把的闲暇时间,无聊的时候把这个socket聊天程序反复敲了几次,尽量弄懂每个细节,应该对以后继续深入学习socket编程和多线程编程有帮助。


下面这个socket聊天程序的例子主要分为三个部分和N个容器。

1.需要一个继承SocketServer的服务器类 Server。

2.需要一个继承Thread的客服端类 Client。

3.需要一个消息处理类(广播类)处理每个Client产生的聊天记录。


然后还需要多个全局的容器:一个消息队列,负责储存所有Client产生的消息;一个Thread队列,记录加入到server的所有client线程。



具体代码如下:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.LinkedList;

/**
 * User: Administrator
 * Date: 14-1-29
 * Time: 下午7:40
 */
public class Server  extends ServerSocket{
    private  FileOutputStream serverLogs = new FileOutputStream("D:/connect.log",true);
    private static final int PORT = 18888; //指定server端 端口号
    private static LinkedList<String> messageHandler = new LinkedList<String>(); //存放消息的队列
    private static ArrayList<Client> threads = new ArrayList<Client>();//存放client线程
    private static ArrayList<String> nikeNameList = new ArrayList<String>();//存放nikeName
    private static boolean isClean = true;
   public Server() throws Exception{
       super(PORT);
       //启动消息管理线程
       new MessageHandler();
       //记录服务端启动日志
       Calendar calendar = Calendar.getInstance();
       byte[] logs = (calendar.getTime().toString()+"server is start.").getBytes();
       serverLogs.write(logs);
       //响应client连接请求,把socket对象放客户端线程
       try {
           while(true){
               Socket socket = accept();
               new Client(socket);
           }
       } finally {
           close();
       }

   }

    public static void main(String[] args) throws Exception{
        new Server();
    }

    class MessageHandler extends Thread{

        public MessageHandler(){
              start();
        }

        public void run(){
            while(true){
                if(!isClean){
                    String message = messageHandler.getLast();
                    for(Client client:threads){
                        client.pushMessages(message);
                    }
                    isClean = true;
                }
                //  isClean = true; 这句不能写在这里,想想为什么?


            }
        }
    }
    class Client extends Thread{
        private BufferedReader in;
        private PrintWriter out ;
        private String nikeName;
        private String input;
        private Socket clientSocket;
        public Client(Socket client) throws Exception{
            this.clientSocket = client;
            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            out = new PrintWriter(clientSocket.getOutputStream(),true);
            out.println("------------welcome-------------");
            out.println("please input your nikeName:");
            start();
        }
        @Override
        public void run() {
            try {
                input = in.readLine();
                nikeName = input;
                int count = 0;
                while (!"bye".equals(input)){
                    if(count++ == 0){
                        out.println("ok,welcome<"+nikeName+">,you can talk now.");
                        nikeNameList.add(nikeName);
                        threads.add(this);
                        messageHandler.addLast("<" + nikeName + "> entered the chartRoom.");
                    }else {
                        if("L".equals(input)){
                            showAllUsers();
                        }else {
                            pullMessages("<"+nikeName+">:"+input);
                        }

                    }
                     input = in.readLine();
                }
                out.println("bye <"+nikeName+">");
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    //pullMessages("<"+nikeName+"> is left the room."); 这句不能写在这里,呵呵,想想为什么?
                    nikeNameList.remove(nikeName);
                    threads.remove(this);
                    in.close();
                    out.close();
                    if(!clientSocket.isClosed()){
                        clientSocket.close();
                    }
                    pullMessages("<"+nikeName+"> is left the room."); //应该写在这里
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        //向当前线程展示所有在线用户
        public void showAllUsers(){
            out.println("------show all users-------");
            for(String name : nikeNameList){
                out.println("<"+name+"> is online.");
            }
            out.println("---------------------------");
        }

        //把当前线程的消息放入消息队列
        public void pullMessages(String message){
            messageHandler.addLast(message);
            isClean = false;
        }

        //推送消息
        public void pushMessages(String message){
           out.println(message);
        }
    }
}

打开CMD 输入 telnet localhost 18888 会产生一个连接到server的client线程,输入昵称后就可以开始聊天了(可以打开多个,然后自己和自己聊天)。

上面的程序实现了如下功能:记录服务器启动日志,多线程聊天。查看当前进入聊天室的人列表。 如果感兴趣还可以加入查看聊天记录,显示聊天时间等。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值