这是一个基于TCP连接的手写聊天室。
约定以@name:为私聊某人,sendToOther方法实现群聊。ChatUtils类为了释放资源。用到的基础知识:TCP Socket编程,多线程,IO等
项目所用到的类
服务器端ChatServer
package com.shun.chathome;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
/**
* @Author: JamesLee
* @Description:
* @Date: Created in 18:00
* @Modify By:
*/
public class Channel implements Runnable{
private Socket client;
private DataOutputStream dos;
private DataInputStream dis;
private boolean isRunning;
private String name ;
public Channel(Socket client){
try {
this.client=client;
this.isRunning = true;
this.dos = new DataOutputStream(client.getOutputStream());
this.dis = new DataInputStream(client.getInputStream());
this.name = dis.readUTF();
this.send("欢迎你加入这个聊天群");
this.sendToOthers(this.name+"加入聊天群..",true);
} catch (IOException e) {
release();
System.out.println(" ---- Server--Init ----Error-");
}
}
private void sendToOthers(String msg,boolean isSystem){
if (!isSystem){
char head = msg.charAt(0);
if (head!='@') {
for (Channel c : ChatServer.all) {
if (!c.equals(this)) {
c.send(this.name+"说:"+msg);
}
}
}else{
int index = msg.indexOf(":");
String name = msg.substring(1,index);
for (Channel c : ChatServer.all) {
if (c!=this){
if (c.name.equals(name)){
sendToOthers(this.name+"偷偷对你说:"+msg,false);
}
}
}
}
}else{
for(Channel c : ChatServer.all){
if (!c.equals(this)){
c.send("系统提示:"+msg);
}
}
}
}
@Override
public void run() {
while (isRunning) {
String msg = receive();
sendToOthers(msg,false);
}
}
public void send(String msg){
if (msg.length()>0)
try {
dos.writeUTF(msg);
dos.flush();
System.out.println(msg);
} catch (IOException e) {
release();
System.out.println(" ---- Server--Send--Msg----Error-");
}
}
public String receive(){
String msg = "";
try {
msg=dis.readUTF();
System.out.println(this.name+":"+msg);
} catch (IOException e) {
release();
System.out.println("---Server--Read--Msg--Error!---");
}
return msg;
}
public void release(){
isRunning = false;
ChatServer.all.remove(this);
ChatUtils.close(dis,dos,client);
}
}
客户端ChatClient
package com.shun.chathome;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
/**
* @Author: JamesLee
* @Description:
* @Date: Created in 17:07
* @Modify By:
*/
public class ChatClient {
public static void main(String[] args) throws IOException {
Socket client = new Socket("localhost",8888);
Scanner sc = new Scanner(System.in);
System.out.print("请输入您的姓名:");
String name = sc.nextLine();
System.out.println("---------client-----");
new Thread(new Send(client,name)).start();
new Thread(new Receive(client)).start();
}
}
工具类 ChatUtils
package com.shun.chathome;
import java.io.Closeable;
import java.io.IOException;
/**
* @Author: JamesLee
* @Description:
* @Date: Created in 17:57 2020
* @Modify By:
*/
public class ChatUtils {
public static void close(Closeable ... targets){
for (Closeable target:targets){
try {
if (null!=target){
target.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
连接类Channel
package com.shun.chathome;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
/**
* @Author: JamesLee
* @Description:
* @Date: Created in 18:00
* @Modify By:
*/
public class Channel implements Runnable{
private Socket client;
private DataOutputStream dos;
private DataInputStream dis;
private boolean isRunning;
private String name ;
public Channel(Socket client){
try {
this.client=client;
this.isRunning = true;
this.dos = new DataOutputStream(client.getOutputStream());
this.dis = new DataInputStream(client.getInputStream());
this.name = dis.readUTF();
this.send("欢迎你加入这个聊天群");
this.sendToOthers(this.name+"加入聊天群..",true);
} catch (IOException e) {
release();
System.out.println(" ---- Server--Init ----Error-");
}
}
private void sendToOthers(String msg,boolean isSystem){
if (!isSystem){
char head = msg.charAt(0);
if (head!='@') {
for (Channel c : ChatServer.all) {
if (!c.equals(this)) {
c.send(this.name+"说:"+msg);
}
}
}else{
int index = msg.indexOf(":");
String name = msg.substring(1,index);
for (Channel c : ChatServer.all) {
if (c!=this){
if (c.name.equals(name)){
c.send(c.name+"偷偷对你说:"+msg.substring(index+1));
}
}
}
}
}else{
for(Channel c : ChatServer.all){
if (!c.equals(this)){
c.send("系统提示:"+msg);
}
}
}
}
@Override
public void run() {
while (isRunning) {
String msg = receive();
sendToOthers(msg,false);
}
}
public void send(String msg){
if (msg.length()>0)
try {
dos.writeUTF(msg);
dos.flush();
System.out.println(msg);
} catch (IOException e) {
release();
System.out.println(" ---- Server--Send--Msg----Error-");
}
}
public String receive(){
String msg = "";
try {
msg=dis.readUTF();
System.out.println(this.name+":"+msg);
} catch (IOException e) {
release();
System.out.println("---Server--Read--Msg--Error!---");
}
return msg;
}
public void release(){
isRunning = false;
ChatServer.all.remove(this);
ChatUtils.close(dis,dos,client);
}
}
客户端接收 Receive
package com.shun.chathome;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
/**
* @Author: JamesLee
* @Description:
* @Date: Created in 18:17 2020
* @Modify By:
*/
public class Receive implements Runnable{
private boolean isRunning;
private DataInputStream dis;
private Socket client;
public Receive(Socket client){
try {
this.client = client;
this.dis = new DataInputStream(client.getInputStream());
this.isRunning = true;
} catch (IOException e) {
release();
System.out.println("---客户端接收端初始化失败----");
}
}
@Override
public void run() {
while (isRunning){
receive();
}
}
private void receive(){
try {
System.out.println(dis.readUTF());
} catch (IOException e) {
release();
System.out.println("-------客户端接收错误-------");
}
}
private void release(){
isRunning = false;
ChatUtils.close(dis,client);
}
}
客户端发送Send
package com.shun.chathome;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/**
* @Author: JamesLee
* @Description:
* @Date: Created in 18:17
* @Modify By:
*/
public class Send implements Runnable{
private DataOutputStream dos;
private BufferedReader console;
private Socket client;
boolean isRunning = true;
public Send(Socket client,String name){
try {
this.client = client;
dos = new DataOutputStream(client.getOutputStream());
send(name);
} catch (IOException e) {
release();
System.out.println("----客户端发送初始化出错---");
}
}
public void send(String msg){
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
release();
System.out.println("---客户端发送出现错误---");
}
}
@Override
public void run() {
while (isRunning){
send(getMsgFromConsole());
}
}
private String getMsgFromConsole(){
console = new BufferedReader(new InputStreamReader(System.in));
String msg = "";
try {
msg = console.readLine();
} catch (IOException e) {
release();
System.out.println("---发送端控制台读取出现错误---");
}
return msg;
}
private void release(){
isRunning=false;
ChatUtils.close(dos,client);
}
}
运行结果
假装这里有图,图片挂了,结果的话很简单,如果你是初学者,你只需要在同一个包内定义这六个类,然后将代码复制进去,先运行ChatServer,再运行Client(可以运行多个),然后可以在控制台里输入输出啦。
结语:
不积跬步无以至千里,不积小流无以成江海
望与诸君共同进步