我正在研究多客户端套接字并且它的工作正常,但我想到如何通过将输入的字符串传输到所有客户端来公开通信。
例如,如果有3个客户端A,B和C,客户端A向服务器发送“foo”,我希望服务器也将“foo”流式传输到客户端B和C.
服务器模块:
package multiclient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String args[]) {
Socket s = null;
ServerSocket ss2 = null;
System.out.println("Server Listening......");
try {
ss2 = new ServerSocket(4445); // can also use static final PORT_NUM , when defined
} catch (IOException e) {
e.printStackTrace();
System.out.println("Server error");
}
while (true) {
try {
s = ss2.accept();
System.out.println("connection Established");
ServerThread st = new ServerThread(s);
st.start();
} catch (Exception e) {
e.printStackTrace();
System.out.println("Connection Error");
}
}
}
}
class ServerThread extends Thread {
String line = null;
BufferedReader is = null;
PrintWriter os = null;
Socket s = null;
public ServerThread(Socket s) {
this.s = s;
}
public void run() {
try {
is = new BufferedReader(new InputStreamReader(s.getInputStream()));
os = new PrintWriter(s.getOutputStream());
} catch (IOException e) {
System.out.println("IO error in server thread");
}
try {
line = is.readLine();
while (line.compareTo("QUIT") != 0) {
os.println(line);
os.flush();
System.out.println("Response to Client : " + line);
line = is.readLine();
}
} catch (IOException e) {
line = this.getName(); //reused String line for getting thread name
System.out.println("IO Error/ Client " + line + " terminated abruptly");
} catch (NullPointerException e) {
line = this.getName(); //reused String line for getting thread name
System.out.println("Client " + line + " Closed");
} finally {
try {
System.out.println("Connection Closing..");
if (is != null) {
is.close();
System.out.println(" Socket Input Stream Closed");
}
if (os != null) {
os.close();
System.out.println("Socket Out Closed");
}
if (s != null) {
s.close();
System.out.println("Socket Closed");
}
} catch (IOException ie) {
System.out.println("Socket Close Error");
}
}//end finally
}
}
客户端模块:
package multiclient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
public class Client {
public static void main(String args[]) throws IOException{
InetAddress address=InetAddress.getLocalHost();
Socket s1=null;
String line=null;
BufferedReader br=null;
BufferedReader is=null;
PrintWriter os=null;
try {
s1=new Socket(address, 4445); // You can use static final constant PORT_NUM
br= new BufferedReader(new InputStreamReader(System.in));
is=new BufferedReader(new InputStreamReader(s1.getInputStream()));
os= new PrintWriter(s1.getOutputStream());
}
catch (IOException e){
e.printStackTrace();
System.err.print("IO Exception");
}
System.out.println("Client Address : "+address);
System.out.println("Enter Data to echo Server ( Enter QUIT to end):");
String response=null;
try{
line=br.readLine();
while(line.compareTo("QUIT")!=0){
os.println(line);
os.flush();
response=is.readLine();
System.out.println("Server Response : "+response);
line=br.readLine();
}
}
catch(IOException e){
e.printStackTrace();
System.out.println("Socket read Error");
}
finally{
is.close();os.close();br.close();s1.close();
System.out.println("Connection Closed");
}
}
}
答案 0 :(得分:0)
服务器可以保留所有客户端套接字的集合(直到一个被关闭)。当客户端消息到达时,服务器将其写入所有客户端套接字。
但是有一个问题,socket.write()是阻塞的,所以如果我们在循环中执行它,慢速客户端将阻塞其余的客户端。如果没有太多客户端,您可以生成一个新线程来写入每个单独的套接字。
在阻塞IO世界中,要实现真正的全双工协议,服务器必须为每个客户端提供两个线程,一个用于读取,一个用于写入。
如果你足够勇敢,你也可以尝试NIO ......
答案 1 :(得分:0)
有很多例子。搜索聊天服务器。如果您不介意使用框架,那么一个好的问题是Netty,请查看SecureChat示例以获取有效的代码。这是一个简短而有针对性的例子。
编辑:该链接将您带到示例代码。
答案 2 :(得分:0)
我建议:
1.将您创建的线程保存在ArrayList中
2.在Server中创建一个名为writeString的方法和一个锁
private final Lock mutex = new ReentrantLock(true);
private ArrayList<ServerThread> list = new ArrayList<ServerThread>();
public void writeString(ServerThread t,String s)
{
mutex.lock();
for(ServerThread th:list)
if(th!=null && th!=t) //different from the thread receiving the string
th.writeString(s); //send string to other threads
mutex.unlock();
}
3。在ServerThread类中,实现writeString方法并添加一个Lock
private final Lock mutex = new ReentrantLock(true);
public void writeString(String s)
{
mutex.lock();
os.println(s);
os.flush();
mutex.unlock();
}
4。通过修改构造函数
保持对主服务器线程的引用 //in ServerThread
private Server parent=null;
SeverThread(Socket s, Server parent)
{
this.parent=parent;
/*the rest of the code*/
}
//in Server
ServerThread st = new ServerThread(s,this);
st.start();
list.add(st);
当您在ServerThread中读取字符串时,请调用Server writeString方法以通知所有客户端
parent.writeString(this,s); //calls the method we created at 2.