您的位置:首页 > 编程语言 > Java开发

Java Socket编程 多线程server和client通信demo

2017-04-24 18:00 399 查看
server代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class TCPServer {
public static Map<String, Socket> socketMap = new HashMap<String, Socket>();

public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(10000);// 创建服务器socket,监听10000端口

// 开启信息发送的线程
sendMsgThread();
// 循环进行与客户端的连接
while (true) {
Socket socket = server.accept();// 阻塞,等待客户端的连接
serverThread(socket);// 新建通信线程
}
}

/**
*
* @Title: serverThread
* @Desc: 多线程 接收客户端信息
*
* @param socket
*            参数
*
*/
public static void serverThread(Socket socket) {
// 新线程
new Thread(new Runnable() {
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try {
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

4000
String msg = in.readLine();// 读取客户发来的信息
socketMap.put(msg.split(" ")[1], socket);
while (true) {
if ("bye".equals(msg.split(":")[1].trim())) {// 若客户端发来bye,则跳出循环,即关闭当前线程
socketMap.remove(socket);//将socket从map中移除
break;
}
System.out.println(msg);// 打印客户端发来的信息
msg = in.readLine();// 读取客户发来的信息
}
} catch (IOException e) {
e.printStackTrace();
} finally {// 关闭io
in.lines();
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}
}).start();// 开启线程,将自动运行run方法
}

/**
*
* @Title: sendMsgThread
* @Desc: 发送信息给客户端
*
*/
public static void sendMsgThread() {
new Thread(new Runnable() {
PrintWriter out = null;
BufferedReader toClient = null;

public void run() {
try {
while (true) {
System.out.println("say to who?:");
Scanner s = new Scanner(System.in);//输入要发送的客户端的name
String name = s.nextLine();
Socket socket = socketMap.get(name);//从map中获取name对应的socket
if (socket == null) {
System.out.println("this client not exist");
continue;
}
out = new PrintWriter(socket.getOutputStream());
System.out.println("say what?:");
toClient = new BufferedReader(new InputStreamReader(System.in));
String send = toClient.readLine();

out.println("server " + Thread.currentThread().getId() + " say: " + send);// 将信息发送给客户端
out.flush();// 刷新
}
} catch (IOException e) {
e.printStackTrace();
} finally {
out.close();
try {
toClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}
}).start();
}
}


client代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class TCPClient {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("localhost", 10000);// 创建socket,连接localhost(127.0.0.1)的10000端口
System.out.println("enter your name:");
Scanner s = new Scanner(System.in);// 控制台输入name
String name = s.nextLine();// 读取
System.out.println("say to server:");

PrintWriter out = new PrintWriter(socket.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
readThread(socket);
while (true) {
String msg = reader.readLine();// 读取控制台输入信息
out.println("=========>>>client " + name + " say: " + msg);// 发送信息到服务器
if ("bye".equals(msg)) {
break;
}
out.flush();
}
reader.close();
out.close();
socket.close();
}

/**
*
* @Title: readThread
* @Desc: 新开线程读取服务器发来的信息
*
*  @param socket 参数
*
*/
public static void readThread(Socket socket) {
new Thread(new Runnable() {
public void run() {
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true) {
String str = in.readLine();
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();

}
}


效果图:

server部分,由于控制台打印按顺序的,看着有点乱,接收到的消息和发送的消息是独立的



客户端1,xiaoming



客户端2,xiaohong



思路,主要把读和写用不同的线程分开弄,要不然读写容易冲突,会阻塞,客户端和服务器都如此

客户端的读取用了多个线程,每个对应一个客户端,写则统一在一个线程里处理,通过map获取对应的socket

基本实现多个客户端和服务器的通信
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: