实现方案
TCP + 多线程
基本说明
user1
user1 实际上是作为服务器端,在本机暴露9999端口,使用accept()函数实现监听,需要先开始user1的程序,再开启user2程序。
user1有类 user1_send 和 user1_listen 分别负责发送和监听。
user2
user2 实际上是作为客户端,使用Socket(“127.0.0.1”,9999)设置目标地址和端口,发送连接请求。
user2有类 user2_send 和 user2_listen 分别负责发送和监听。
代码实现
user1.java
public class user1 {
public static void main(String[] args) throws IOException {
System.out.println("======用户1已上线=======");
ServerSocket serverSocket = new ServerSocket(9999);
//当没有接受到套接字请求时,程序阻塞在accept()函数处,
//一旦接收到套接字请求,则开启相应的监听和发送线程,并且进行下一个循环,建立新的套接字
while (true){
//不断接收客户请求,为每一个客户创建一个独立的线程去处理每个客户的请求
Socket socket = serverSocket.accept();
new Thread(new user1_listen(socket)).start();
new Thread(new user1_send(socket)).start();
}
}
}
//用来监听user2的请求
class user1_listen implements Runnable{
private Socket socket;
public user1_listen(Socket socket) {
this.socket = socket;
}
public void run() {
try {
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
while (true){
System.out.println(ois.readObject());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//当客户断开连接或出现异常,服务器的socket需要断开,没有必要保持连接而浪费资源
try {
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
//用来发送消息
class user1_send implements Runnable{
private Socket socket;
public user1_send(Socket socket) {
this.socket = socket;
}
public void run() {
try {
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
Scanner scanner = new Scanner(System.in);
while(true){
//读取键盘输入
String string = scanner.nextLine();
//将内容写入通信管道
oos.writeObject("user1发送:"+string);
oos.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
user2.java
package com.bhy.qq;
import org.json.simple.JSONObject;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Scanner;
public class user2 {
private static Socket socket;
private static boolean connection_state = false;
public static void main(String[] args) {
connect();
System.out.println("======用户2已上线=======");
if(connection_state){
new Thread(new user2_listen(socket)).start();
new Thread(new use2_send(socket)).start();
}
}
//连接user1
public static void connect(){
try {
socket = new Socket("127.0.0.1",9999);
connection_state = true;
} catch (IOException e) {
e.printStackTrace();
connection_state=false;
}
}
}
//用来接收user1传来的信息
class user2_listen implements Runnable{
private Socket socket;
public user2_listen(Socket socket) {
this.socket = socket;
}
public void run() {
try {
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
while (true){
System.out.println(ois.readObject());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//用来发送消息
class use2_send implements Runnable{
private Socket socket;
public use2_send(Socket socket) {
this.socket = socket;
}
public void run() {
try {
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
Scanner scanner = new Scanner(System.in);
while(true){
//读取输入
String string = scanner.nextLine();
oos.writeObject("user2发送:"+string);
oos.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
测试
先开启user1,再开启user2。
user1先发送 hello,user2 , I ’ m user1!!
user2发送 hello , I ’ m user 2! ^*^
user1窗口
user2窗口
拓展——增加user3
此外,可以无限增加用户与user1通信,因为user1是服务端,并且不断有新的套接字监听,可以建立多个套接字连接。
关键代码如下
user1.java
//当没有接受到套接字请求时,程序阻塞在accept()函数处,
//一旦接收到套接字请求,则开启相应的监听和发送线程,并且进行下一个循环,建立新的套接字
while (true){
//不断接收客户请求,为每一个客户创建一个独立的线程去处理每个客户的请求
Socket socket = serverSocket.accept();
new Thread(new user1_listen(socket)).start();
new Thread(new user1_send(socket)).start();
}
测试
user3.java
和user2代码几乎一样,把代码中的 2 改成 3 即可
public class user3{
private static Socket socket;
private static boolean connection_state = false;
public static void main(String[] args) {
connect();
System.out.println("======用户3已上线=======");
if(connection_state){
new Thread(new user3_listen(socket)).start();
new Thread(new use3_send(socket)).start();
}
}
//连接user1
public static void connect(){
try {
socket = new Socket("127.0.0.1",9999);
connection_state = true;
} catch (IOException e) {
e.printStackTrace();
connection_state=false;
}
}
}
class user3_listen implements Runnable{
private Socket socket;
public user3_listen(Socket socket) {
this.socket = socket;
}
public void run() {
try {
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
while (true){
System.out.println(ois.readObject());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class use3_send implements Runnable{
private Socket socket;
public use3_send(Socket socket) {
this.socket = socket;
}
public void run() {
try {
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
Scanner scanner = new Scanner(System.in);
while(true){
String string = scanner.nextLine();
oos.writeObject("user3发送:"+string);
oos.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
结果:
user3输入
3testing
user2输入
2testing
但是新的问题会出现,user1发送的消息会随机发送给user2或user3,因为此时user1同时有两个发送线程,不知道发送的时候会用到哪一个。在这里不给出解决方案(主要不会/(ㄒoㄒ)/~~
所以user1只能实现接收多方信息的功能,不能精准发送消息