Java网络----Socket, 多线程实现内网多人聊天及一对一聊天

本文属于网络编程,才用Socket+多线程编程,实现使用控制台进行多人互动聊天,以及一对一互动聊天,
服务器端代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URLDecoder;
import java.util.ArrayList;

public class SimpleServer {

    //用于保存当前连接的用户  
    public static ArrayList<Socket> socketList=new ArrayList<Socket>();

    /**
     * 服务器主函数
     * @param args
     * @throws Exception
     */
    public static void main(String[] args)throws Exception {
        //创建一个serverSocket,用于监听客户端Socket的连接请求  
        ServerSocket serverSocket = new ServerSocket(10002);//10002为此服务器的端口号  
        System.out.println("服务启动.....");  
        //采用循环不断接收来自客户端的请求  
        while (true) {  
            //每当接收到客户端的请求时,服务器端也对应产生一个Socket  
            Socket socket = serverSocket.accept();  
            System.out.println("服务连接....");  
            // 把连接的客户端加入到list列表中  
            socketList.add(socket);  
            System.out.println("当前有:"+socketList.size()+"个客户端连接");
            //启动一个新的线程  
            //任务线程,每个连接用都有一个属于自己专用的任务线程  
            //这个线程内会处理信息的发送和响应  
            new MyThread(socket,socketList).start();  
        } 
    }
}
class MyThread extends Thread {

    //一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。建立网络通信连接至少要一对端口号(socket)
    Socket client;  

    ArrayList<Socket> clients;  

    BufferedReader br; 

    public MyThread(Socket client,ArrayList<Socket> clients)throws Exception {  
        super();  
        this.client = client;  
        this.clients = clients;  

        br = new BufferedReader(new InputStreamReader(this.client.getInputStream()));  
    }  

    //把接收到的消息发送给各客户端  
    public void run() {  
        try {  
            String content=null;  
            while(true){  
                //从某个客户端读取信息  
                if((content=br.readLine())!=null) {  
                    for(Socket socket:clients){  
                        if(client!=socket){  
                            //把读取到的消息发送给各个客户端  
                            PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);  
                            pw.println(content);  
                        }  
                    }  
                    content = URLDecoder.decode(content, "UTF-8");  
                    System.out.println(content);  

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

}

客户端代码:

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.URLDecoder;

public class Client {
    /** 
     * @param args 
     */  
    public static void main(String[] args) throws Exception {  
        // TODO Auto-generated method stub  
        //创建连接到本机,端口为10002的socket  
        System.out.println("123");
        Socket client = new Socket("192.168.1.49", 10002);  

        new MyThread(client).start();  
        InputStream is = client.getInputStream();  
        BufferedReader br = new BufferedReader(new InputStreamReader(is));  

        while (true) {  
            String msg = br.readLine();  
            //对收到的信息进行解码  
            msg=URLDecoder.decode(msg, "UTF-8");  
            System.out.println(msg);  
        }  
    }  

}

客户端线程方法:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URLEncoder;
import java.net.UnknownHostException;

public class MyThread extends Thread {
    Socket client;
    //消息发送人名称,即本机的名称
    String hostName = "";
    public MyThread(Socket client) {  
        super();  
        this.client = client;  
        try {
            InetAddress addr = InetAddress.getLocalHost();
            hostName =addr.getHostName().toString(); //获取本机计算机名称
        } catch (UnknownHostException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }
    public void run() { 
        // 发出消息  
        try {  
            BufferedReader br = new BufferedReader(new InputStreamReader(  
                    System.in));  
            PrintWriter pw = new PrintWriter(client.getOutputStream(), true);  
            // 把输入的内容输出到socket  
            while (true) {  
                String msg = br.readLine();  
                //对发出的消息进行编码  
                msg = URLEncoder.encode(hostName + "说:"+ msg, "UTF-8");  
                pw.println(msg);  
            }  
        } catch (IOException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
    } 
}

至此简单的多人聊天已经实现
运行服务器,再运行两台客户机,进行消息发送,通过服务器发送其他客户机,
效果如下:
服务器打印内容:

服务启动…..
服务连接….
当前有:1个客户端连接
服务连接….
当前有:2个客户端连接
Vip_HYP-PC说:我是客户A
Vip_HYP-PC说:我是客户B

客户机B打印内容:

Vip_HYP-PC说:我是客户A
我是客户B

当然这样的效果过于简陋,,比如我们可以让客户机来查看有几个用户?以及对某个特定的用户进行消息发送?想到这些,那就在服务器端先加上业务逻辑把.

先进行客户端改变:
删除hostName 定义实现,改为电脑ip标识:

    //消息发送人名称
    String userName = "";
    //消息发送人IP地址,身份的唯一标识
    String hostIP="";

MyThread方法修改

    public MyThread(Socket client) {  
        super();  
        this.client = client;  
        try {
            InetAddress addr = InetAddress.getLocalHost();
            hostIP=addr.getHostAddress().toString();//获取本机的计算机IP
        } catch (UnknownHostException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }

run方法增加username判断

String msg = br.readLine();  
//刚登录,进行用户名填写
if(userName.equals("")){
    //对发出的消息进行编码  
    msg = URLEncoder.encode(hostIP+"__"+ msg, "UTF-8");//添加用户IP做唯一标识  
   pw.println(msg); 
}else{
    //添加用户IP做唯一标识
    msg = URLEncoder.encode(hostIP+"__"+userName + "__说:"+ msg, "UTF-8");  
    pw.println(msg);
}

接下来是服务器端代码修改:
首先mian方法中,对每次连接用户发送一个消息,进行用户名注册

PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
pw.println("请输入您的用户名,进行聊天");
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//创建用户名
String content = "";
if((content=br.readLine())!=null) {  
    //以__拆分消息内容,ip,username
    content = URLDecoder.decode(content, "UTF-8");
    String[] contents = content.split("__");
    userNameMap.put(contents[0], contents[1]);
}

重点到了,对获取到的消息进行判断执行:

if((content=br.readLine())!=null) {
    content = URLDecoder.decode(content, "UTF-8");
    //以__拆分消息内容,ip,username+内容
    String[] contents = content.split("__");
    if(contents.length==3){
        if(contents[2].equals("说:1")){//查看所有登录用户
             for(Socket socket:clients){ 
                 if(client!=socket){//不是自身
                      PrintWriter pw = new PrintWriter(client.getOutputStream(), true);
                      pw.println("用户名:"+userNameMap.get(socket.getInetAddress().toString())+",ip地址:"+socket.getInetAddress());
                 }
             }
          }
      }
      if(contents[2].equals("说:2")){//进行指定人聊天
          //进行消息指定发送
      }
      if(contents[2].equals("说:e")){//退出指定人聊天
         //销毁两用户的一对一关联,未实现
      }else{
         for(Socket socket:clients){  
              if(client!=socket){  
                  //把读取到的消息发送给各个客户端  
                  PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);  
                  pw.println(contents[1]+'['+contents[0]+']'+contents[2]);  
               } 
            }
        }
    }
}

贴出效果图:
这里写图片描述
这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_26555463/article/details/77478893