Java之Socket客户端间通信(dos版)

dos版本的聊天室

目的:实现客户端对客户端的通信

思路:客户端发送信息到服务器(保存客户1的内容),之后判断链接来的客户端是不是某个地址,然后,写出去客户端2。
前提,能实现多用户的连接(Thread)

一、首先创建一个消息类,该类只有两个属性:

  • 一是接收消息的客户端的编号
  • 二是消息内容
    实现代码如下:
package com.xiaogao;

import java.io.Serializable;

/*
 * 消息类,该类只有两个属性:
 * 一个是接收消息的客户端的编号,一个是消息内容
 */
public class Message implements Serializable{
	//客户端编号
	int id;
	//消息内容
	String msg;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getMsg() {
		return msg;
	}
	public void setMsg(String msg) {
		this.msg = msg;
	}
	
}

二、然后创建一个服务器,转发客户端信息

package com.xiaogao;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

/*
 * 服务器,该类创建了serverSocket对象,绑定本地的8989端口,
 * 声明静态变量sessionMap来保存所有已连接的客户端,并给每个客户端分配一个编号
 */
public class SocketNotifyServer {
	//socket服务器
	ServerSocket serverSocket=null;
	//用来存放已连接的客户端的socket信息
	static Map<Integer,Socket> sessionMap=new HashMap<Integer,Socket>();
	
	public void socket(){
		try {
			//创建serverSocket,绑定端口8989
			serverSocket =new ServerSocket(8989);
			System.out.println("服务器开启!!!");
			//客户端编号
			int i=1;
			//实现多个客户端的连接
			while(true){
				Socket socket=serverSocket.accept();
				System.out.println("客户端:"+i+"连接成功~~~");
				if(socket!=null){
					//将socket放入map,key为客户端编号
					sessionMap.put(i, socket);
					//开启线程处理本次对话
					Thread thread=new Thread(new NotifyHandler(socket,sessionMap));
					thread.setDaemon(true);
					thread.start();//启动并运行线程
					i++;
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args) throws IOException{
		new SocketNotifyServer().socket();
		
	}

}

三、接着创建一个消息处理类
利用构造方法,得到消息发送方以及所有的已连接客户端

package com.xiaogao;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Map;

/*
 * 消息处理类,重写构造方法,
 * 得到消息发送方以及所有的已连接客户端
 */
public class NotifyHandler extends Thread{
	Socket socket=null;
	InputStream in=null;
	Map<Integer,Socket> sessionMap=null;
	
	public NotifyHandler(Socket socket,Map<Integer,Socket> sessionMap){
		this.socket=socket;
		this.sessionMap=sessionMap;
	}
	
	public void run(){
		try {
            in = socket.getInputStream();
            ObjectInputStream ois = new ObjectInputStream(in);
            // 实现一次连接多次通话
            while (true) {
                try {
                    Message msg = (Message) ois.readObject();
                    System.out.println("消息接受对象:客户端" + msg.getId() + ",\t消息内容:" + msg.getMsg());
                    // 发送数据
                    try {
                        Socket targetSocket = sessionMap.get(msg.getId());
                        OutputStream out = targetSocket.getOutputStream();
                        ObjectOutputStream oos = new ObjectOutputStream(out);
                        oos.writeObject(msg);
                        System.out.println("服务端已转发");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    if (socket.isClosed()) {
                        break;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    try {
                        socket.close();
                        break;
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
	}
}

四、最后是创建客户端

package com.xiaogao;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;

/*
 * 客户端
 */
public class MsgSocketClient {
	Socket socket=null;
	InputStreamReader input=null;
	InputStream in=null;
	OutputStream out=null;
	
	public void socketStart(){
		try {
			socket=new Socket("127.0.0.1",8989);
			System.out.println("客户端1启动————");
			//接受返回的数据
			new Thread(){
				public void run(){
					try {
						while(true){
							in=socket.getInputStream();
							ObjectInputStream ois=new ObjectInputStream(in);
							Message msg=(Message)ois.readObject();
							System.out.println("返回数据:"+msg.getMsg());
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}.start();
			out=socket.getOutputStream();
			ObjectOutputStream oos=new ObjectOutputStream(out);
			while(true){
				input=new InputStreamReader(System.in);//阻塞着等待输入
				String msg=new BufferedReader(input).readLine();
				Message message=new Message();
				message.setId(2);
				message.setMsg(msg);
				oos.writeObject(message);
				System.out.println("已发送");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			//关闭流和连接
			try {
				in.close();
				out.close();
				socket.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		new MsgSocketClient().socketStart();
	}

}

/*
 * 当(客户端1)启动的时候id属性的值为2,当(客户端2)启动时,id属性为1。
 * 此处把消息接收代码放在前面,是因为while (true){input = new InputStreamReader(System.in);
 * 这里在阻塞着等待输入,如果接收消息的代码放在这段代码下方,会导致在没有发过消息的时候,
 * 接收消息的线程不会启动,收不到别的客户端发来的消息
*/

此聊天室,可以一方多次发送,解决了一来一回造成的堵塞问题。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值