java 网络编程--------小型聊天室(TCP)

Send.java

作用:对传进去的Socket类型对象进行初始化操作,并可从控制台获取消息并通过服务器端发送到其他客户端。

package Test_Net;

import java.io.Closeable;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;

public class Send implements Runnable {
     private DataOutputStream dos ;
     private Socket client;
     boolean isrunning = false;
     String name;
     public Send(Socket client,String name){
         isrunning = true;
         this.name = name;
         this.client = client;
         try {
             dos = new DataOutputStream(client.getOutputStream());
             dos.writeUTF(name);
         } catch (IOException e) {
            free();
         }
     }

     public void send(String message){
         try {
             dos.writeUTF(message);
             dos.flush();
         } catch (IOException e) {
             free();
         }
     }
     public String getInputString(){
         Scanner input = new Scanner(System.in);
         String message = input.next();
         return message;
     }

    public void run() {
         while (isrunning){
             String message = getInputString();
             if(!"".equals(message)){
                 send(message);
             }
         }

    }
   public void free(){
         isrunning = false;
         close(dos,client);
   }
    public static void close(Closeable... targets ) {
        for(Closeable target:targets) {
            try {
                if(null!=target) {
                    target.close();
                }
            }catch(Exception e) {

            }
        }
    }
}

Receive.java

作用:对传进去的Socket类型对象进行初始化操作,并能将接收到的信息在控制台打印出来。

package Test_Net;

import java.io.Closeable;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;

public class Receive implements Runnable {

    private DataInputStream dis = null;
    private Socket client =null;
    private boolean isrunning = false;
    public Receive(Socket client){
       this.client = client;
       try {
           dis = new DataInputStream(client.getInputStream());
       } catch (IOException e) {
           free();
       }
       isrunning = true;

   }
   public String receice(){
       String message = "";
       try {
           message = dis.readUTF();
       } catch (IOException e) {
           free();
       }
       return message;
   }
    public void run() {
       while (isrunning){
          String message = receice();
          if(!"".equals(message)){
              System.out.println(message);
          }
       }
    }
    public void free(){
       isrunning = false;
       close(dis,client);
    }
    public static void close(Closeable... targets ) {
        for(Closeable target:targets) {
            try {
                if(null!=target) {
                    target.close();
                }
            }catch(Exception e) {

            }
        }
    }
}

costomer.java

作用:针对于服务器端的描述客户端的类,对每一个客户端的初始化以及实现客户端之间进行群聊或私聊功能。

群聊功能很容易实现,只需要将消息遍历costomer容器发送至每一个客户端即可,而私聊功能则需要规定

私聊的语言规范  在这里我的规范是以@开头 再加要发送给对应的客户端的姓名再加上冒号 后边才是消息内容

eg:       @zmj:快叫哥哥  

有了这个规范,只需要对传输过来的字符串进行简单的判断和截取,就可以成功解析出对象的name属性以及

要发送的内容,在容器中遍历查找即可得到对应的接收端对象,从而实现私聊。

package Test_Net;

import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.CopyOnWriteArrayList;

public class costomer implements Runnable {

    private DataInputStream dis;
    private DataOutputStream dos;
    private Socket  client;
    private boolean isrunning;
    private String name;
    CopyOnWriteArrayList<costomer> all;
    public costomer(Socket  client,CopyOnWriteArrayList<costomer> all ) {
        this.all = all;
        this.client = client;
        try {
            dis = new DataInputStream(client.getInputStream());
            dos =new DataOutputStream(client.getOutputStream());
            isrunning =true;
            //获取名称
            this.name =receive();
            this.send("欢迎你的到来");
            sendOthers(this.name+"来了聊天室",true);
        } catch (IOException e) {
            release();
        }
    }
    //接收消息
    private String receive() {
        String msg ="";
        try {
            msg =dis.readUTF();
        } catch (IOException e) {
            release();
        }
        return msg;
    }
    //发送消息
    private void send(String msg) {
        try {
            dos.writeUTF(msg);
            dos.flush();
        } catch (IOException e) {
            release();
        }
    }

    /**
     * 私聊规范:
     *
     * @+name+:+内容
     */
    private void sendOthers(String msg,boolean isallbody) {
        boolean isone = false;
        isone = msg.startsWith("@");
       if(!isone) {
           for (costomer other : all) {
               if (other == this) { //自己
                   continue;
               }
               if (isallbody) {
                   other.send(this.name + "对所有人说:" + msg);//群聊消息
               } else {
                   other.send(msg); //系统消息
               }
           }
       }
       else {
           String name= msg.substring(msg.indexOf('@')+1,msg.indexOf(':'));
           String infor = msg.substring(msg.indexOf(':')+1);
           for(costomer t:all){
               if(name.equals(t.name)){
                   t.send(this.name+" (悄悄对你说):"+infor);
               }
           }
       }
    }
    //释放资源
    private void release() {
        this.isrunning = false;
        free();
        all.remove(this);
        sendOthers(this.name+"离开...",false);
    }
    public void free(){
        isrunning = false;
        close(dis,dos,client);
    }
    public static void close(Closeable... targets ) {
        for(Closeable target:targets) {
            try {
                if(null!=target) {
                    target.close();
                }
            }catch(Exception e) {

            }
        }
    }
    @Override
    public void run() {
        while(isrunning) {
            String msg = receive() ;
            if(!msg.equals("")) {
                //send(msg);
                sendOthers(msg,true);
            }
        }
    }
}

TestChat.java

作用:实际的客户端程序,可多次运行建立多个客户端连接,实现多人聊天。

其中加入多线程,可使接收消息和发送消息并发执行,更贴合实际的多人聊天。

package Test_Net;

import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;

public class TestChat {
    public static void main(String[] args) throws IOException {
        System.out.println("-*-------客户端-------*-");
        System.out.println("输入用户名");
        Scanner input = new Scanner(System.in);
        Socket client = new Socket("localhost",6667);
            String name = input.next();
            new Thread(new Send(client,name)).start();
           new Thread(new Receive(client)).start();
    }
}

TestServerchat.java

作用:实际的服务器端程序,创建服务器,并循环阻塞式与客户端建立连接,并将所有建立连接的客户端存储至容器中,便于对群聊私聊进行操作。

package Test_Net;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.CopyOnWriteArrayList;

public class TestServerchat {
    public static void main(String[] args) throws IOException {

        System.out.println("------------服务器端-------------");
        ServerSocket server = new ServerSocket(6667);
        CopyOnWriteArrayList<costomer> all = new CopyOnWriteArrayList<costomer>();
        while (true){
            Socket client = server.accept();
            System.out.println("一个客户端建立了连接..");
            costomer c = new costomer(client,all);
            all.add(c);
            new Thread(c).start();
        }
    }
}

总结:基于TCP编程的小型多人聊天室,加深了对多线程,以及输入输出流、网络编程的理解。是个很好的练习项目。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
部分代码如下:client: /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package client; /** * * @author Administrator */ import java.awt.*; import java.io.*; import java.net.*; import java.applet.*; import java.util.Hashtable; public class ClientChat extends Applet implements Runnable { Socket socket=null; DataInputStream in=null; DataOutputStream out=null; InputNameTextField 用户提交昵称界面=null; ChatArea 用户聊天界面=null; Hashtable listTable; Label 提示条; Panel north, center; Thread thread; public void init() { int width=getSize().width; int height=getSize().height; listTable=new Hashtable(); setLayout(new BorderLayout()); 用户提交昵称界面=new InputNameTextField(listTable); int h=用户提交昵称界面.getSize().height; 用户聊天界面=new ChatArea("",listTable,width,height-(h+5)); 用户聊天界面.setVisible(false); 提示条=new Label("正在连接到服务器,请稍等...",Label.CENTER); 提示条.setForeground(Color.red); north=new Panel(new FlowLayout(FlowLayout.LEFT)); center=new Panel(); north.add(用户提交昵称界面); north.add(提示条); center.add(用户聊天界面); add(north,BorderLayout.NORTH); add(center,BorderLayout.CENTER); validate(); } public void start() { if(socket!=null&&in!=null&&out!=null) { try { socket.close(); in.close(); out.close(); 用户聊天界面.setVisible(false); } catch(Exception ee) { } } try { socket = new Socket(this.getCodeBase().getHost(), 6666); in=new DataInputStream(socket.getInputStream()); out=new DataOutputStream(socket.getOutputStream()); } catch (IOException ee) { 提示条.setText("连接失败"); } if(socket!=null) { InetAddress address=socket.getInetAddress(); 提示条.setText("连接:"+address+"成功"); 用户提交昵称界面.setSocketConnection(socket,in,out); north.validate(); } if(thread==null) { thread=new Thread(this); thread.start(); } } public void stop() { try { socket.close(); thread=null; } catch(IOException e) { this.showStatus(e.toString()); } } public void run() { while(thread!=null) { if(用户提交昵称界面.get能否聊天()==true) { 用户聊天界面.setVisible(true); 用户聊天界面.setName(用户提交昵称界面.getName()); 用户聊天界面.setSocketConnection(socket,in,out); 提示条.setText("祝聊天愉快!"); center.validate(); break; } try { Thread.sleep(100); } catch(Exception e) { } } } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值