简介
运用Java套接字我们几乎可以完成一个网络聊天软件的小产品,本文不涉及UI部分,仅对原理部分用代码演示一下。一个可以多人聊天的小功能,在Linux系统上用telnet亲测可用。
服务器代码
package demo0811.demo3;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 使用多线程写一个服务器,端口号为9999
* @author zzw
*
*/
public class ServerMain {
public static ArrayList<Integer> ports=new ArrayList<Integer>();
public static ArrayList<OutputStream> streams=new ArrayList<OutputStream>();
public static void main(String[] args) {
try(ServerSocket server=new ServerSocket(9999)) {
System.out.println("服务器正在运行");
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(50);
while(true) {
Socket socket = server.accept();
int port = socket.getPort();
OutputStream outputStream = socket.getOutputStream();
ports.add(port);
streams.add(outputStream);
newFixedThreadPool.submit(new SocketRunnable(socket,outputStream));
newFixedThreadPool.submit(new NotifyNewersRunnable(port));
}
} catch (Exception ex) {
System.out.println("无法建立监听服务!");
ex.printStackTrace();
}
}
}
package demo0811.demo3;
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.net.Socket;
import java.util.Date;
public class SocketRunnable implements Runnable {
private Socket socket;
private OutputStream outputStream;
public SocketRunnable(Socket socket,OutputStream outputStream) {
this.socket=socket;
this.outputStream=outputStream;
}
@Override
public void run() {
try {
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
Date date = new Date();
outputStreamWriter.write(date.toString()+"\n如发私信,请使用[port]开头"+"\r\n");
outputStreamWriter.flush();
int port = socket.getPort();
while(true) {
if(socket.isConnected()) {
InputStream inputStream = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream,"UTF-8");
BufferedReader bufferedReader = new BufferedReader(reader);
String line;
while((line=bufferedReader.readLine())!=null) {
if(line.startsWith("[")) {
int end=line.indexOf(']');
int target=Integer.parseInt(line.substring(1, end));
int indexOf = ServerMain.ports.indexOf(target);
if(end<0||indexOf<0) {
OutputStreamWriter outputStreamWriter2 =
new OutputStreamWriter(ServerMain.streams.get(ServerMain.ports.indexOf(port)),"UTF-8");
outputStreamWriter2.write("您的私信格式输入有误或端口号不存在!\r\n");
outputStreamWriter2.flush();
} else {
OutputStreamWriter outputStreamWriter2 =
new OutputStreamWriter(ServerMain.streams.get(indexOf),"UTF-8");
outputStreamWriter2.write("端口"+port+"私信:"+line.substring(end+1)+"\r\n");
outputStreamWriter2.flush();
}
} else {
for(int i=0;i<ServerMain.streams.size();i++) {
try {
OutputStreamWriter outputStreamWriter2 = new OutputStreamWriter(ServerMain.streams.get(i),"UTF-8");
outputStreamWriter2.write("端口"+port+"群聊:"+line+"\n");
outputStreamWriter2.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
else {
break;
}
}
socket.close();
} catch (IOException e) {
System.out.println("服务器无法向客户端写入数据!");
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
//不处理
}
}
}
}
package demo0811.demo3;
import java.io.IOException;
public class NotifyNewersRunnable implements Runnable{
private int port;
public NotifyNewersRunnable(int port) {
this.port = port;
}
@Override
public void run() {
int n;
String str="端口"+port+"上线了\r\n";
if((n=ServerMain.streams.size())>1) {
for(int i=0;i<n-1;i++) {
try {
ServerMain.streams.get(i).write(str.getBytes("utf-8"));
ServerMain.streams.get(i).flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}