Java 使用线程处理套接字
我正在开发一个java程序,它本质上是一个聊天室。这是一个课堂作业,所以没有代码请,我只是有一些问题,确定最可行的方式来处理我需要做什么。我已经为单个客户机设置了一个服务器程序,使用线程获取数据输入流,并使用线程处理数据输出流上的发送。我现在需要做的是为每个传入请求创建一个新线程 我的想法是创建一个链表来包含客户机套接字或线程。我遇到的障碍是如何处理向所有客户发送消息的问题。如果我对每个传入消息都有一个线程,那么我如何将它发送到每个客户端套接字 我在想,如果我有一个clientsockets的linkedlist,我就可以遍历这个列表并将它发送给每个人,但是每次我都必须创建一个dataoutputstream。我可以创建dataoutputstreams的linkedlist吗?抱歉,如果这听起来像我在胡扯,但我不想只是开始编码这个,它可能会变得混乱没有一个好的计划。谢谢 编辑 我决定发布到目前为止的代码。我还没有机会测试它,所以任何评论都很好。谢谢Java 使用线程处理套接字,java,sockets,multithreading,Java,Sockets,Multithreading,我正在开发一个java程序,它本质上是一个聊天室。这是一个课堂作业,所以没有代码请,我只是有一些问题,确定最可行的方式来处理我需要做什么。我已经为单个客户机设置了一个服务器程序,使用线程获取数据输入流,并使用线程处理数据输出流上的发送。我现在需要做的是为每个传入请求创建一个新线程 我的想法是创建一个链表来包含客户机套接字或线程。我遇到的障碍是如何处理向所有客户发送消息的问题。如果我对每个传入消息都有一个线程,那么我如何将它发送到每个客户端套接字 我在想,如果我有一个clientsockets的l
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.ServerSocket;
import java.util.LinkedList;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class prog4_server {
// A Queue of Strings used to hold out bound Messages
// It blocks till on is available
static BlockingQueue<String> outboundMessages = new LinkedBlockingQueue<String>();
// A linked list of data output streams
// to all the clients
static LinkedList<DataOutputStream> outputstreams;
// public variables to track the number of clients
// and the state of the server
static Boolean serverstate = true;
static int clients = 0;
public static void main(String[] args) throws IOException{
//create a server socket and a clientSocket
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(6789);
} catch (IOException e) {
System.out.println("Could not listen on port: 6789");
System.exit(-1);
}// try{...}catch(IOException e){...}
Socket clientSocket;
// start the output thread which waits for elements
// in the message queue
OutputThread out = new OutputThread();
out.start();
while(serverstate){
try {
// wait and accept a new client
// pass the socket to a new Input Thread
clientSocket = serverSocket.accept();
DataOutputStream ServerOut = new DataOutputStream(clientSocket.getOutputStream());
InputThread in = new InputThread(clientSocket, clients);
in.start();
outputstreams.add(ServerOut);
} catch (IOException e) {
System.out.println("Accept failed: 6789");
System.exit(-1);
}// try{...}catch{..}
// increment the number of clients and report
clients = clients++;
System.out.println("Client #" + clients + "Accepted");
}//while(serverstate){...
}//public static void main
public static class OutputThread extends Thread {
//OutputThread Class Constructor
OutputThread() {
}//OutputThread(...){...
public void run() {
//string variable to contain the message
String msg = null;
while(!this.interrupted()) {
try {
msg = outboundMessages.take();
for(int i=0;i<outputstreams.size();i++){
outputstreams.get(i).writeBytes(msg + '\n');
}// for(...){...
} catch (IOException e) {
System.out.println(e);
} catch (InterruptedException e){
System.out.println(e);
}//try{...}catch{...}
}//while(...){
}//public void run(){...
}// public OutputThread(){...
public static class InputThread extends Thread {
Boolean threadstate = true;
BufferedReader ServerIn;
String user;
int threadID;
//SocketThread Class Constructor
InputThread(Socket clientSocket, int ID) {
threadID = ID;
try{
ServerIn = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
user = ServerIn.readLine();
}
catch(IOException e){
System.out.println(e);
}
}// InputThread(...){...
public void run() {
String msg = null;
while (threadstate) {
try {
msg = ServerIn.readLine();
if(msg.equals("EXITEXIT")){
// if the client is exiting close the thread
// close the output stream with the same ID
// and decrement the number of clients
threadstate = false;
outputstreams.get(threadID).close();
outputstreams.remove(threadID);
clients = clients--;
if(clients == 0){
// if the number of clients has dropped to zero
// close the server
serverstate = false;
ServerIn.close();
}// if(clients == 0){...
}else{
// add a message to the message queue
outboundMessages.add(user + ": " + msg);
}//if..else...
} catch (IOException e) {
System.out.println(e);
}// try { ... } catch { ...}
}// while
}// public void run() { ...
}
public static class ServerThread extends Thread {
//public variable declaration
BufferedReader UserIn =
new BufferedReader(new InputStreamReader(System.in));
//OutputThread Class Constructor
ServerThread() {
}//OutputThread(...){...
public void run() {
//string variable to contain the message
String msg = null;
try {
//while loop will continue until
//exit command is received
//then send the exit command to all clients
msg = UserIn.readLine();
while (!msg.equals("EXITEXIT")) {
System.out.println("Enter Message: ");
msg = UserIn.readLine();
}//while(...){
outboundMessages.add(msg);
serverstate = false;
UserIn.close();
} catch (IOException e) {
System.out.println(e);
}//try{...}catch{...}
}//public void run(){...
}// public serverThread(){...
}// public class prog4_server
导入java.io.BufferedReader;
导入java.io.DataOutputStream;
导入java.io.IOException;
导入java.io.InputStreamReader;
导入java.net.Socket;
导入java.net.ServerSocket;
导入java.util.LinkedList;
导入java.util.concurrent.BlockingQueue;
导入java.util.concurrent.LinkedBlockingQueue;
公共类prog4_服务器{
//用于保存绑定消息的字符串队列
//它会一直阻塞到可用为止
静态BlockingQueue outboundMessages=新建LinkedBlockingQueue();
//数据输出流的链接列表
//给所有的客户
静态LinkedList输出流;
//用于跟踪客户端数量的公共变量
//以及服务器的状态
静态布尔serverstate=true;
静态int客户端=0;
公共静态void main(字符串[]args)引发IOException{
//创建服务器套接字和客户端套接字
ServerSocket ServerSocket=null;
试一试{
serverSocket=新的serverSocket(6789);
}捕获(IOE异常){
System.out.println(“无法侦听端口:6789”);
系统退出(-1);
}//尝试{…}捕获(IOE异常){…}
插座客户端插座;
//启动等待元素的输出线程
//在消息队列中
OutputThread out=新的OutputThread();
out.start();
while(服务器状态){
试一试{
//等待并接受新客户机
//将套接字传递给新的输入线程
clientSocket=serverSocket.accept();
DataOutputStream ServerOut=新的DataOutputStream(clientSocket.getOutputStream());
InputThread in=新的InputThread(clientSocket,客户端);
in.start();
添加(ServerOut);
}捕获(IOE异常){
System.out.println(“接受失败:6789”);
系统退出(-1);
}//试试{…}抓住{…}
//增加客户端和报告的数量
客户=客户++;
System.out.println(“Client#“+clients+“Accepted”);
}//而(服务器状态){。。。
}//公共静态真空总管
公共静态类OutputThread扩展线程{
//OutputThread类构造函数
OutputThread(){
}//输出线程(…){。。。
公开募捐{
//字符串变量以包含消息
字符串msg=null;
而(!this.interrupted()){
试一试{
msg=outboundMessages.take();
对于(int i=0;i我过去通过为每个客户端连接定义一个“MessageHandler
”类来解决这个问题,该类负责入站/出站消息通信。在内部,处理程序使用一个BlockingQueue
实现,出站消息放置在该实现上(通过内部工作线程)。I/O发送方线程不断尝试从队列中读取(如果需要,则阻塞),并将检索到的每条消息发送到客户端
下面是一些框架示例代码(未经测试):
/**
*我们的消息定义。消息能够将自身写入
*数据输出流。
*/
公共接口消息{
void writeTo(DataOutputStream daos)抛出IOException;
}
/**
*处理程序定义。处理程序包含两个线程:一个用于发送
*一个用于接收信息。它是用一个打开的插座初始化的。
*/
公共类MessageHandler{
专用最终数据输出流daos;
专用最终数据输入流dais;
私有最终线程发送器;
专用终线程接收器;
private final BlockingQueue outboundMessages=新建LinkedBlockingQueue();
公共消息处理程序(套接字skt)引发IOException{
this.daos=新的DataOutputStream(skt.getOutputStream());
this.dais=新的DataInputStream(skt.getInputStream());
//创建负责执行I/O的发送方和接收方线程。
this.sender=新线程(new Runnable()){
公开募捐{
而(!Thread.interrupted()){
Message msg=outboundMessages.take();//将被阻止,直到消息可用为止。
试一试{
msg.writeTo(daos);
}捕获(IOEX异常){
//TODO:处理异常
}
}
}
},String.format(“SenderThread-%s”,skt.getRemoteSocketAddress());
this.receiver=新线程(new Runnable()){
公开募捐{
//TODO:读取DataInputStream并创建入站消息。
}
},String.format(“ReceiverThread-%s”,skt.getRemoteSocketAddress());
sender.start();
receiver.start();
}
/**
*向我提交一份报告
/**
* Our Message definition. A message is capable of writing itself to
* a DataOutputStream.
*/
public interface Message {
void writeTo(DataOutputStream daos) throws IOException;
}
/**
* Handler definition. The handler contains two threads: One for sending
* and one for receiving messages. It is initialised with an open socket.
*/
public class MessageHandler {
private final DataOutputStream daos;
private final DataInputStream dais;
private final Thread sender;
private final Thread receiver;
private final BlockingQueue<Message> outboundMessages = new LinkedBlockingQueue<Message>();
public MessageHandler(Socket skt) throws IOException {
this.daos = new DataOutputStream(skt.getOutputStream());
this.dais = new DataInputStream(skt.getInputStream());
// Create sender and receiver threads responsible for performing the I/O.
this.sender = new Thread(new Runnable() {
public void run() {
while (!Thread.interrupted()) {
Message msg = outboundMessages.take(); // Will block until a message is available.
try {
msg.writeTo(daos);
} catch(IOException ex) {
// TODO: Handle exception
}
}
}
}, String.format("SenderThread-%s", skt.getRemoteSocketAddress()));
this.receiver = new Thread(new Runnable() {
public void run() {
// TODO: Read from DataInputStream and create inbound message.
}
}, String.format("ReceiverThread-%s", skt.getRemoteSocketAddress()));
sender.start();
receiver.start();
}
/**
* Submits a message to the outbound queue, ready for sending.
*/
public void sendOutboundMessage(Message msg) {
outboundMessages.add(msg);
}
public void destroy() {
// TODO: Interrupt and join with threads. Close streams and socket.
}
}