1.0.1
服务器端
package com.lzy.chat01;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Chat {
public static void main(String[] args) throws IOException {
System.out.println("----Server----");
// 1、指定端口 使用ServerSocket创建服务器
ServerSocket server=new ServerSocket(8888);
//2.阻塞式等待连接 accept
Socket client=server.accept();
System.out.println("一个客户建立了链接");
//3接收消息
DataInputStream dis=new DataInputStream(client.getInputStream());
String data=dis.readUTF();
//返回消息
DataOutputStream dos=new DataOutputStream(client.getOutputStream());
dos.writeUTF(data);
dos.flush();
//释放资源
dos.close();
dis.close();
client.close();
}
}
客户端
package com.lzy.chat01;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("----Client----");
Socket client=new Socket("localhost",8888);
//客户端发消息
BufferedReader console=new BufferedReader(new InputStreamReader(System.in));
String msg=console.readLine();
DataOutputStream dos=new DataOutputStream(client.getOutputStream());
dos.writeUTF(msg);
dos.flush();
//客户端接收消息
DataInputStream dis=new DataInputStream(client.getInputStream());
msg=dis.readUTF();
System.out.println(msg);
dos.close();
dis.close();
client.close();
}
}
1.0.2
实现一个客户多次收发消息
存在问题:第二个客户进来时需要等待第一个客户退出才能发送消息
服务器
package com.lzy.chat01;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 在线聊天室:服务器
* 目标:实现一个客户可以正常收发多条消息
* @author Administration
*
*/
public class MultiChat {
public static void main(String[] args) throws IOException {
System.out.println("----Server----");
// 1、指定端口 使用ServerSocket创建服务器
ServerSocket server=new ServerSocket(8888);
//2.阻塞式等待连接 accept
Socket client=server.accept();
System.out.println("一个客户建立了链接");
//3接收消息
DataOutputStream dos=new DataOutputStream(client.getOutputStream());
DataInputStream dis=new DataInputStream(client.getInputStream());
boolean isRunning=true;
while(isRunning) {
//接收消息
String data=dis.readUTF();
//返回消息
dos.writeUTF(data);
dos.flush();
}
//释放资源
dos.close();
dis.close();
client.close();
}
}
客户端
package com.lzy.chat01;
/**
*在线聊天室:客户端
*
*目标:实现一个客户可以正常收发多条消息
*/
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
public class MultiClient {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("----Client----");
//1、建立连接: 使用Socket创建客户端 +服务的地址和端口
Socket client=new Socket("localhost",8888);
//客户端发消息
BufferedReader console=new BufferedReader(new InputStreamReader(System.in));
DataInputStream dis=new DataInputStream(client.getInputStream());
DataOutputStream dos=new DataOutputStream(client.getOutputStream());
boolean isRunning=true;
while(isRunning) {
String msg=console.readLine();
dos.writeUTF(msg);
dos.flush();
//3.获取消息
msg=dis.readUTF();
System.out.println(msg);
}
dos.close();
dis.close();
client.close();
}
}
1.0.3
使用多线程实现多个客户可以正常收发多条消息
服务器端
package com.lzy.chat02;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 在线聊天室:服务器
* 目标:使用多线程实现多个客户可以正常收发多条消息
* 问题:
* 1.代码不好维护
* 2.客户端读写没有分开 必须先写后读
* @author Administration
*
*/
public class TMultiChat {
public static void main(String[] args) throws IOException {
System.out.println("----Server----");
// 1、指定端口 使用ServerSocket创建服务器
ServerSocket server=new ServerSocket(8888);
//2.阻塞式等待连接 accept
while(true) {
Socket client=server.accept();
System.out.println("一个客户建立了链接");
new Thread(()->{
DataOutputStream dos=null;
DataInputStream dis=null;
//3接收消息
try {
dos=new DataOutputStream(client.getOutputStream());
dis=new DataInputStream(client.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
boolean isRunning=true;
while(isRunning) {
//接收消息
String data;
try {
data=dis.readUTF();
//返回消息
dos.writeUTF(data);
dos.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//释放资源
try {
if(null!=dos) {
dos.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(null!=dis) {
dis.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(null!=client) {
client.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}).start();
}
}
}
客户端
package com.lzy.chat02;
/**
*在线聊天室:客户端
*
*目标:使用多线程实现多个客户可以正常收发多条消息
*/
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
public class TMultiClient {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("----Client----");
//1、建立连接: 使用Socket创建客户端 +服务的地址和端口
Socket client=new Socket("localhost",8888);
//客户端发消息
BufferedReader console=new BufferedReader(new InputStreamReader(System.in));
DataInputStream dis=new DataInputStream(client.getInputStream());
DataOutputStream dos=new DataOutputStream(client.getOutputStream());
boolean isRunning=true;
while(isRunning) {
String msg=console.readLine();
dos.writeUTF(msg);
dos.flush();
//3.获取消息
msg=dis.readUTF();
System.out.println(msg);
}
dos.close();
dis.close();
client.close();
}
}
1.0.4
封装使用多线程实现多个客户可以正常收发多条消息
服务器
package com.lzy.chat03;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 在线聊天室:服务器
* 目标:封装使用多线程实现多个客户可以正常收发多条消息
* 问题:
* 1.代码不好维护
* 2.客户端读写没有分开 必须先写后读
* @author Administration
*
*/
public class TMultiChat {
public static void main(String[] args) throws IOException {
System.out.println("----Server----");
// 1、指定端口 使用ServerSocket创建服务器
ServerSocket server=new ServerSocket(8888);
while(true) {
//2.阻塞式等待连接 accept
Socket client=server.accept();
System.out.println("一个客户建立了链接");
new Thread(new Channel(client)).start();
}
}
//一个客户代表一个Channel
static class Channel implements Runnable{
private DataInputStream dis;
private DataOutputStream dos;
private Socket client;
private boolean isRunning;
public Channel(Socket client) {
this.client = client;
try {
dis=new DataInputStream(client.getInputStream());
dos=new DataOutputStream(client.getOutputStream());
isRunning=true;
} catch (IOException e) {
// TODO Auto-generated catch block
release();
}
}
//接收消息
public String receive() {
String msg="";
try {
msg=dis.readUTF();
} catch (IOException e) {
// TODO Auto-generated catch block
release();
}
return msg;
}
//发送消息
public void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
release();
}
}
//释放资源
public void release() {
this.isRunning=false;
SxtUtil.close(dis,dos,client);
}
@Override
public void run() {
while(isRunning) {
String msg=receive();
if(!msg.equals("")) {
send(msg);
}
}
}
}
}
客户端
package com.lzy.chat03;
/**
*在线聊天室:客户端
*
*目标:使用多线程实现多个客户可以正常收发多条消息
*/
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
public class TMultiClient {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("----Client----");
//1、建立连接: 使用Socket创建客户端 +服务的地址和端口
Socket client=new Socket("localhost",8888);
//2.客户端发送消息
new Thread(new Send(client)).start();
new Thread(new Receive(client)).start();
}
}
工具类
package com.lzy.chat03;
import java.io.Closeable;
import java.io.IOException;
/**
* 工具类
* @author Administration
*
*/
public class SxtUtil {
public static void close(Closeable...targets) {
for(Closeable target:targets) {
try {
if(null!=target) {
target.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
发送消息
package com.lzy.chat03;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class Send implements Runnable{
private DataOutputStream dos;
private BufferedReader console;
private Socket client;
private boolean isRunning;
public Send(Socket client) {
this.client = client;
console=new BufferedReader(new InputStreamReader(System.in));
this.isRunning=true;
try {
dos=new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
System.out.println("====1====");
release();
}
}
//发送消息
public void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
System.out.println("====3====");
release();
}
}
/**
* 从控制台获取消息
* @return
*/
public String getStrFromConsole() {
try {
return console.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
release();
}
return"";
}
//释放资源
public void release() {
this.isRunning=false;
SxtUtil.close(dos,client);
}
@Override
public void run() {
while(isRunning) {
String msg=getStrFromConsole();
if(!msg.equals("")) {
send(msg);
}
}
}
}
接受消息
package com.lzy.chat03;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
public class Receive implements Runnable {
private DataInputStream dis;
private Socket client;
private boolean isRunning;
public Receive(Socket client) {
this.client = client;
this.isRunning=true;
try {
dis=new DataInputStream(client.getInputStream());
} catch (IOException e) {
System.out.println("====2====");
release();
}
}
//接收消息
public String receive() {
String msg="";
try {
msg=dis.readUTF();
} catch (IOException e) {
System.out.println("====4====");
release();
}
return msg;
}
//释放资源
public void release() {
this.isRunning=false;
SxtUtil.close(dis,client);
}
@Override
public void run() {
while(isRunning) {
String msg=receive();
if(!msg.equals("")) {
System.out.println(msg);
}
}
}
}
1.0.5
群聊中可以对某人进行私聊
服务器
package com.lzy.chat05;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 在线聊天室:服务器
* 目标:加入容器实现群聊
*
* @author Administration
*
*/
public class Chat {
private static CopyOnWriteArrayList<Channel> all=new CopyOnWriteArrayList<>();//建立数组容器
public static void main(String[] args) throws IOException {
System.out.println("----Server----");
// 1、指定端口 使用ServerSocket创建服务器
ServerSocket server=new ServerSocket(8888);
while(true) {
//2.阻塞式等待连接 accept
Socket client=server.accept();
System.out.println("一个客户建立了链接");
Channel c=new Channel(client);
all.add(c);//管理所有成员
new Thread(c).start();
}
}
//一个客户代表一个Channel
static class Channel implements Runnable{
private DataInputStream dis;
private DataOutputStream dos;
private Socket client;
private boolean isRunning;
private String name;
public Channel(Socket client) {
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) {
// TODO Auto-generated catch block
release();
}
}
//接收消息
public String receive() {
String msg="";
try {
msg=dis.readUTF();
} catch (IOException e) {
// TODO Auto-generated catch block
release();
}
return msg;
}
//发送消息
public void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
release();
}
}
/**
* 群聊:获取自己的消息 发给其他人
* 私聊:约定数据格式:@xxx:msg
*
*/
public void sendOthers(String msg,boolean isSys) {
boolean isPrivate=msg.startsWith("@");//msg字符是否以@开头
if(isPrivate) {
//私聊
int idx=msg.indexOf(":");
//获取目标和数据
String targetName=msg.substring(1,idx);
msg=msg.substring(idx+1);//substring()返回一个字符串,该字符串是此字符串的子字符串。
for(Channel other:all) {
if(other.name.equals(targetName)) {
//目标
other.send(this.name+"悄悄地对您说:"+msg);
break;
}
}
}else {
for(Channel other:all) {
if(other==this) {
//自己
continue;
}
if(!isSys) {
other.send(this.name+"对所有人说:"+msg);//群聊消息
}else {
other.send(msg);//系统消息
}
}
}
}
//释放资源
public void release() {
this.isRunning=false;
SxtUtil.close(dis,dos,client);
//退出
all.remove(this);
sendOthers(this.name+"离开大家庭...",true);
}
@Override
public void run() {
while(isRunning) {
String msg=receive();
if(!msg.equals("")) {
//send(msg);
sendOthers(msg,false);
}
}
}
}
}
客户端
package com.lzy.chat05;
/**
*在线聊天室:客户端
*
*目标:使用多线程实现多个客户可以正常收发多条消息
*/
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("----Client----");
BufferedReader br =new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入用户名:");
String name=br.readLine();
//1、建立连接: 使用Socket创建客户端 +服务的地址和端口
Socket client=new Socket("localhost",8888);
//2.客户端发送消息
new Thread(new Send(client,name)).start();
new Thread(new Receive(client)).start();
}
}
发送
package com.lzy.chat05;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/**
* 使用多线程封装:发送端
* 1.发送消息
* 2.从控制台获取消息
* 3.释放资源
* 4.重写run
* @author Administration
*
*/
public class Send implements Runnable{
private DataOutputStream dos;
private BufferedReader console;
private Socket client;
private boolean isRunning;
private String name;
public Send(Socket client,String name) {
this.client = client;
console=new BufferedReader(new InputStreamReader(System.in));
this.isRunning=true;
this.name=name;
try {
dos=new DataOutputStream(client.getOutputStream());
//发送名称
send(name);
} catch (IOException e) {
System.out.println("====1====");
this.release();
}
}
//发送消息
public void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
System.out.println("====3====");
release();
}
}
/**
* 从控制台获取消息
* @return
*/
public String getStrFromConsole() {
try {
return console.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
release();
}
return"";
}
//释放资源
public void release() {
this.isRunning=false;
SxtUtil.close(dos,client);
}
@Override
public void run() {
while(isRunning) {
String msg=getStrFromConsole();
if(!msg.equals("")) {
send(msg);
}
}
}
}
接受
package com.lzy.chat05;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
public class Receive implements Runnable {
private DataInputStream dis;
private Socket client;
private boolean isRunning;
public Receive(Socket client) {
this.client = client;
this.isRunning=true;
try {
dis=new DataInputStream(client.getInputStream());
} catch (IOException e) {
System.out.println("====2====");
release();
}
}
//接收消息
public String receive() {
String msg="";
try {
msg=dis.readUTF();
} catch (IOException e) {
System.out.println("====4====");
release();
}
return msg;
}
//释放资源
public void release() {
this.isRunning=false;
SxtUtil.close(dis,client);
}
@Override
public void run() {
while(isRunning) {
String msg=receive();
if(!msg.equals("")) {
System.out.println(msg);
}
}
}
}
工具类(释放资源)
package com.lzy.chat05;
import java.io.Closeable;
import java.io.IOException;
/**
* 工具类
* @author Administration
*
*/
public class SxtUtil {
public static void close(Closeable...targets) {
for(Closeable target:targets) {
try {
if(null!=target) {
target.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}