您的位置:首页 > 理论基础 > 计算机网络

[置顶] 多线程+网络编程实现聊天室

2015-07-17 19:03 561 查看
服务器:

package com.thread.socket.demo;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

/**
* 服务器
* 创建多线程服务器
* @author Qixuan.Chen
* 创建时间:2015年7月3日
*/
public class MultiServer {

private List<ChannelManager> all = new ArrayList<ChannelManager>();

public static void main(String[] args) throws IOException {
new MultiServer().start();

}

public void start() throws IOException
{
ServerSocket server = new ServerSocket(9999);
while(true)
{
Socket client = server.accept();
ChannelManager channel = new ChannelManager(client);
all.add(channel);//统一管理
new Thread(channel).start();//一条道路
}
}

/**
* 一个内部类,
* 一个客户端,一条道路
* 1、输入流
* 2、输出流
* 3、接收数据
* 4、发送数据
*/
class ChannelManager implements Runnable{

private DataInputStream dis;
private DataOutputStream dos;
private boolean isRunning = true;
private String name;

public void run(){
while(isRunning)
{
sendOthers(receive(),false);
}
}

//无参数构造函数
public ChannelManager(){

}

//初始化
public ChannelManager(Socket client){

try {
dis = new DataInputStream(client.getInputStream());
dos = new DataOutputStream(client.getOutputStream());

this.name = dis.readUTF();
//System.out.println(this.name);
this.send("欢迎进入聊天室");

sendOthers(this.name+"进入了聊天室",true);
} catch (IOException e) {
CloseUtil.closeAll(dos,dis);
isRunning = false;
}

}

//接收数据
private String receive()
{
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
CloseUtil.closeAll(dis);
isRunning = false;
all.remove(this);//移除自身
}
return msg;

}

//发送数据
private void send(String msg)
{
if(null==msg||msg.equals(""))
{
return;
}
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
CloseUtil.closeAll(dos);
isRunning = false;
all.remove(this);//移除自身
}
}

//发送给其他客户端
private void sendOthers(String msg,boolean sys)
{
//是否为私聊 约定
if(msg.startsWith("@")&& msg.indexOf(":")>-1)
{
//获取name
String name = msg.substring(1,msg.indexOf(":"));
String contant = msg.substring(msg.indexOf(":")+1);
for(ChannelManager other:all)
{
if(other.name.equals(name))
{
other.send(this.name+"对你悄悄的说:"+contant);
}
}
}
else {
for(ChannelManager other:all)
{
if(other ==this)
{
continue;
}

if(sys==true)//系统信息
{
other.send("系统信息:"+msg);
}
else {
//发送其它客户端
other.send(this.name+"对所有人说"+msg);
}

}
}
/*
//遍历容器
for(MyChannel others:all)
{
if(others == this)
{
continue;
}
//发送给其他客户端
others.send(msg);
}*/

}

}//内部类:END

}
发送数据处理类:
package com.thread.socket.demo;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

/**
* 发送数据线程,用于发送数据
* 发送信息(供客服端使用)
* @author Qixuan.Chen
* 创建时间:2015年7月17日
*/
public class Send implements Runnable{

//控制台输入流
private BufferedReader console;
//管道输出流
private DataOutputStream dos;
//控制线程标识
private boolean isRunning = true;
//名称
private String name;

public void run() {
while(isRunning)
{
send( getMsgFromConsole());
}
}

//初始化
public Send() {
console = new BufferedReader(new InputStreamReader(System.in));
}

public Send(Socket client,String name)
{
this();
try {
dos = new DataOutputStream(client.getOutputStream());
this.name = name;
send(this.name);
} catch (IOException e) {
//e.printStackTrace();
System.out.println(e);
}
}

//1、从控制台接收数据
private String getMsgFromConsole()
{
try {
return console.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}

/**
* 1、从控制台接收数据
* 2、发送数据
*/
public void send(String msg)
{

try {
if(null!=msg&& !msg.equals(""))
{
dos.writeUTF(msg);
dos.flush();//强制刷新
}
} catch (IOException e) {
//e.printStackTrace();
isRunning = false;
CloseUtil.closeAll(dos,console);
}
}

}


接收数据处理类:
package com.thread.socket.demo;

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

/**
* 接收线程:用于接收数据
* 接收信息(供客服端使用)
* @author Qixuan.Chen
* 创建时间:2015年7月17日
*/
public class Receive implements Runnable{
//管道的数据输入流
private DataInputStream dis ;
//线程标识
private boolean isRunning = true;

public Receive() {
}
public Receive(Socket client) {
try {
dis = new DataInputStream(client.getInputStream());
} catch (IOException e) {
isRunning = false;
CloseUtil.closeAll(dis);
System.out.println("close");
}
}

//接收数据的方法
public String receive()
{
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
isRunning = false;
CloseUtil.closeAll(dis);
}
return msg;
}

public void run() {
//线程体
while(isRunning){
System.out.println(receive());
}
}

}


关闭流方法:
package com.thread.socket.demo;

import java.io.Closeable;
import java.io.IOException;

/**
* 关闭流的方法
*/
public class CloseUtil {
public static void closeAll(Closeable ... io)
{
for(Closeable temp:io)
{
if(null==temp)
{
try {
temp.close();
} catch (IOException e) {
System.out.println(e);
e.printStackTrace();
}
}
}
}
}

客户端:
package com.thread.socket.demo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

/**
* 客户端
* 创建客户端:发送数据+接收数据
* 写出数据:输出流
* 读取数据:输入流
* 输入流与输出流在同一个线程内 应该独立出来
* 加入名称
*/
public class Client {
public static void main(String[] args) throws IOException
{
System.out.println("请输入用户名:");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String name = br.readLine();
if(name.equals(""))
{
return;
}
Socket client = new Socket("localhost",9999);
new Thread(new Send(client,name)).start();//一条路径
new Thread(new Receive(client)).start();//一条路径

}
}

运行效果图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: