前言
这是我用java写的Android聊天室项目的服务端,当然也可用于java项目。这里写了两个服务端,一个只实现多人聊天,一个可多人,可一对一。
Android客户端
源码
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.HashMap;
public class Run2 {
private final static int PORT = 12345;
public static ArrayList<Socket> list ;
public static void main(String[] args) throws IOException {
new Thread(new startServer()).start();
}
static class startServer implements Runnable{
@Override
public void run() {
try {
ServerSocket server = new ServerSocket(PORT);
list = new ArrayList<>();
while (true) {
Socket client = server.accept();
System.out.println(client);
list.add(client);
new choicesend2(client,list).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class choicesend2 extends Thread {
private Socket socket;
private DataOutputStream dos;
private DataInputStream dis;
public ArrayList<Socket> list;
public choicesend2(Socket socket, ArrayList<Socket> list) {
this.socket = socket;
this.list = list;
}
@Override
public void run() {
try {
dis = new DataInputStream(socket.getInputStream());
while (true) {
String title;
String name;
String ip;
char[] temp = new char[200];
int len = 0;
char c = 0;
while ((c = dis.readChar()) != '\t') {
temp[len] = c;
len++;
}
title = new String(temp, 0, len);
len = 0;
while ((c = dis.readChar()) != '\t') {
temp[len] = c;
len++;
}
name = new String(temp, 0, len);
len = 0;
while ((c = dis.readChar()) != '\t') {
temp[len] = c;
len++;
}
ip = new String(temp, 0, len);
System.out.println(ip);
for (Socket socket : list) {
if(socket==this.socket)
continue;
dos = new DataOutputStream(socket.getOutputStream());
try {
dos.writeChars(title);
dos.writeChar('\t');
dos.writeChars(name);
dos.writeChar('\t');
dos.writeInt(0);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
问题:我们在多人聊天时是用ArrayList集合来存放每一个连接上的Socket对象,但是显然我们自己无法判断出那个是我要去传输数据的Socket
解决方案:把ArrayList改为HashMap,键存放识别用户的信息,值存放Socket,发送时根据键判断是否要与此时的Socket建立连接
比如我的键传的ip,根据ip判断是否建立连接(显然这种不能在一台电脑上相互传输,(HashMap无重复))
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.HashMap;
public class Run {
private final static int PORT = 12345;
public static ArrayList<Socket> list ;
public static HashMap<String,Socket> hs;
public static void main(String[] args) throws IOException {
new Thread(new startServer()).start();
}
static class startServer implements Runnable{
@Override
public void run() {
try {
ServerSocket server = new ServerSocket(PORT);
hs = new HashMap<>();
while (true) {
Socket client = server.accept();
System.out.println(client);
hs.put(client.getInetAddress().toString(),client);
new choicesend(client,hs).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class choicesend extends Thread {
private Socket socket;
private String key;
private DataOutputStream dos;
private DataInputStream dis;
public HashMap<String,Socket> hs;
public choicesend(Socket socket, HashMap<String,Socket> hs) {
this.socket = socket;
this.hs = hs;
}
@Override
public void run() {
try {
dis = new DataInputStream(socket.getInputStream());
while (true) {
String title;
String name;
String ip;
char[] temp = new char[200];
int len = 0;
char c = 0;
while ((c = dis.readChar()) != '\t') {
temp[len] = c;
len++;
}
title = new String(temp, 0, len);
len = 0;
while ((c = dis.readChar()) != '\t') {
temp[len] = c;
len++;
}
name = new String(temp, 0, len);
len = 0;
while ((c = dis.readChar()) != '\t') {
temp[len] = c;
len++;
}
ip = new String(temp, 0, len);
System.out.println(ip);
if(ip.equals("255.255.255.255")){
for(String sendip : hs.keySet()){
System.out.println(sendip+"集合中的ip");
Socket socket = hs.get(sendip);
dos = new DataOutputStream(socket.getOutputStream());
try {
dos.writeChars(title);
dos.writeChar('\t');
dos.writeChars(name);
dos.writeChar('\t');
dos.writeInt(0);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
else{
for(String sendip : hs.keySet()){
sendip = sendip.substring(1,sendip.length());
if(ip.equals(sendip)){
Socket socket = hs.get(sendip);
if(socket!=null)
dos = new DataOutputStream(socket.getOutputStream());
try {
System.out.println("我发了");
dos.writeChars(title);
dos.writeChar('\t');
dos.writeChars(name);
dos.writeChar('\t');
dos.writeInt(1);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
反思:
这种一对一的局限性显然很大,只能通过ip去匹配,如果想通过id去找人又如何匹配呢?我认为可以写一个注册登录界面,当登录时就可以获取到用户的Socket,用HashMap去维护,键传入id,值传入Socket对象,这样只要是登录的都传进了我们的HashMap,当需要一对一时就可以用id去匹配聊天。