一. 前言
最近看了一个视频,是关于做聊天室的,学习了一下,这里我将我看过后,自己做出来的代码在此记录一份。这是socket的基本运用,大神请绕道哟,学习者可参考,如需转载,请注明出处!谢谢!
二. 客户端
package com.zdl.tcptest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class Client {
private Socket socket;
private Scanner scanner;
public Client(){
try {
socket = new Socket("localhost",8080);
System.out.println("连接已创建!");
} catch (Exception e) {
e.printStackTrace();
}
}
public void start(){
System.out.println("欢迎使用zhangdl聊天室!");
try {
//开启输入流,接收聊天信息
new Thread(new ClientHandler(socket)).start();
//获取输出流
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os,"UTF-8");
PrintWriter pw = new PrintWriter(osw,true);
scanner = new Scanner(System.in);
//输入昵称(第一行)
System.out.println("请输入昵称");
pw.println(scanner.nextLine());
System.out.println("昵称创建成功,快去聊天吧!↓↓↓↓↓↓");
while(true){
pw.println(scanner.nextLine());
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Client user = new Client();
user.start();
}
class ClientHandler implements Runnable{
private Socket socket;
public ClientHandler(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is,"UTF-8");
BufferedReader br = new BufferedReader(isr);
String message = null;
while((message = br.readLine())!=null){
System.out.println(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
三. 服务端
package com.zdl.tcptest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Server {
private ServerSocket serverSocket;
private List<PrintWriter> outList = new ArrayList<PrintWriter>();
private Map<String,PrintWriter> outMap = new HashMap<>();
public Server(){
try {
System.out.println("8080端口服务等待创建!");
serverSocket = new ServerSocket(8080);
System.out.println("8080端口服务已创建!");
} catch (IOException e) {
e.printStackTrace();
}
}
public void start(){
System.out.println("等待连接");
Socket socket = null;
try {
while(true){
socket = serverSocket.accept();
ExecutorService pool = Executors.newFixedThreadPool(10);
pool.execute(new ServerHandler(socket));
}
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Server server = new Server();
server.start();
}
// public synchronized void add(PrintWriter pw){
// outList.add(pw);
// }
// public synchronized void remove(PrintWriter pw){
// outList.remove(pw);
// }
public synchronized void sendAll(String message){
for(Entry<String, PrintWriter> entity : outMap.entrySet()){
// pw.println(message);
entity.getValue().println("[群聊]"+message);
}
}
public synchronized void addMap(String nickName , PrintWriter pw){
outMap.put(nickName, pw);
}
public synchronized void removeMap(String nickName){
outMap.remove(nickName);
}
public synchronized void sendOther(String nickName , String message , PrintWriter myself, String myname){
PrintWriter other = outMap.get(nickName);
if(other!=null){
other.println("["+myname+"私聊]"+message);
myself.println("[私聊"+nickName+"]"+message);
}else{
sendAll(message);
}
}
class ServerHandler implements Runnable{
private Socket socket;
private String address;
private String nickName;
public ServerHandler(Socket socket){
this.socket = socket;
address = socket.getInetAddress().getHostAddress();
System.out.println(address+" 已上线");
}
@Override
public void run() {
PrintWriter pw = null;
try {
//获取输出流
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os,"UTF-8");
pw = new PrintWriter(osw,true);
//获取输入流
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is,"UTF-8");
BufferedReader br = new BufferedReader(isr);
//获取昵称(第一行)
nickName = br.readLine();
addMap(nickName, pw);
System.out.println("聊天室在线人数为:"+outMap.size());
//获取聊天信息
String message = null;
while((message = br.readLine())!=null){//此处会报错是因为windows读取结束后会报错,Linux会返回null
if(message.length()>4){
int end = message.trim().indexOf(" ");
if("@to".equals(message.trim().substring(0,3))&&end!=-1){// 设定@toXXXX xxxxx 的格式表示发给个人
String otherName = message.trim().substring(3,end);//他人的昵称
message = message.trim().substring(end+1);
sendOther(otherName, message , pw, nickName);
}else {
sendAll(nickName+":"+message);
}
}else{
sendAll(nickName+":"+message);
}
}
} catch (IOException e) {
} finally {
try {
if(pw!=null){
removeMap(nickName);
}
System.out.println("聊天室在线人数为:"+outMap.size());
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
四. 简要说明
该代码是我看了视频后自己写出来的,可能有些地方还有瑕疵,如有发现,还请指正。
注释比较少,又看不懂的可以也可以问我。
目前该代码还是在console中运行的,如果感兴趣的可以用swing做可视化界面,就可以实现做出类似qq、飞秋之类的聊天工具了。
加油!