Java 从套接字多次打开读/写流
在我有Java 从套接字多次打开读/写流,java,sockets,Java,Sockets,在我有ServerSocket监听传入连接的类中,下面是代码: while(isRunning) { try { Socket s = mysocketserver.accept(); acknowledgeClient(s); new ClientHandler(s).start(); //Start new thread to serve the client, and get back to accept new connec
ServerSocket
监听传入连接的类中,下面是代码:
while(isRunning)
{
try
{
Socket s = mysocketserver.accept();
acknowledgeClient(s);
new ClientHandler(s).start(); //Start new thread to serve the client, and get back to accept new connections.
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
下面是acknowledgeClient(sockets)
code
ObjectInputStream in = new ObjectInputStream(s.getInputStream);
ObjectOutputStream out = new ObjectOutputStream(s.getOutStream);
String msg = in.readObject().toString();
System.out.println(msg+" is Connected"); //Show who's connected
out.writeObject("success"); //Respond with success.
in.close();
out.close();
ClientHandler的run()
方法
try
{
in = new ObjectInputStream(client.getInputStream());
out = new ObjectOutputstream(client.getOutputStream());
String msg = "";
while(!msg.equalsIgnoreCase("bye"))
{
msg = in.readObject().toString();
System.out.println("Client Says - "+msg);
out.writeObject("success");
}
in.close();
out.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
下面是客户端程序如何与Echo服务器通信的方式
try
{
int count = 10;
client = new Socket("localhost",8666);
in = new ObjectInputStream(client.getInputStream());
out = new ObjectOutputstream(client.getOutputStream());
out.writeObject("Foo");
System.out.println("Connection Status : "+in.readObject().toString());
while(count>0)
{
out.writeObject("Hello!");
String resp = in.readObject().toString(); //Getting EOFException here.
System.out.println("Sent with :"+resp);
count--;
Thread.sleep(1000);
}
out.close();
in.close();
client.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
您可能已经注意到,在连接后确认客户端后,我关闭读/写流,从为客户端提供服务的新线程开始,我再次打开流,从服务器开始从连接的套接字读/写,但只要我尝试读取发送时服务器的响应Hello
通过客户端,它会以EOFEException
崩溃,而不是获得成功
我知道EOF发生的原因,但不知道为什么会发生在这里,我不会尝试读取流中没有任何内容的套接字(它应该有服务器编写的成功)
在服务器打印出Hello之前,客户端试图读取套接字是否为时过早代码>在其末尾并作为响应写入成功
p.S.:我知道放这么多代码问问题不是一个好方法,我们希望在这里得到问题的答案并理解它,而不是让别人解决我们的问题然后逃之夭夭。因此,我提供了这么多代码来显示问题的各个方面。
我再次打开流,从服务器开始从连接的套接字读/写
一旦流关闭,就不能再打开它。事实上,您根本不能以这种方式在同一个流上使用两个对象流
相反,您应该为输入和输出创建一个对象流,并且只创建一次,并且在完成之前不要关闭它。我研究了ObjectInputStream的源代码,似乎对原始输入流的引用s.getInputStream()
存储在ObjectInputStream中
关闭ObjectInputStream时,s.getInputStream()
也将关闭
输入流一旦关闭,就无法再次打开。因此,您会得到一个EOFEException,它指示您处于流的末尾(因为流无法再次打开)
您应该这样做来确认客户
在ClientHandler的run()方法中:
try {
// acknowledge client
ObjectInputStream in = new ObjectInputStream(s.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(s.getOutStream());
String msg = in.readObject().toString();
System.out.println(msg+" is Connected"); //Show who's connected
out.writeObject("success"); //Respond with success.
// end acknowledge client
String msg = "";
while(!msg.equalsIgnoreCase("bye"))
{
msg = in.readObject().toString();
System.out.println("Client Says - "+msg);
out.writeObject("success");
}
in.close();
out.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
如果您想用单独的方法隔离确认代码,只需确保在不关闭流的情况下维护对同一ObjectInputStream的正确引用,然后传递引用。好吧,看看这个程序,我编写它是为了理解多个客户端和服务器通信,你的问题在这个节目中得到了回答
客户端代码
public class ClientWala {
public static void main(String[] args) throws Exception{
Boolean b = true;
Socket s = new Socket("127.0.0.1", 4444);
System.out.println("connected: "+s.isConnected());
OutputStream output = s.getOutputStream();
PrintWriter pw = new PrintWriter(output,true);
// to write data to server
while(b){
if (!b){
System.exit(0);
}
else {
pw.write(new Scanner(System.in).nextLine());
}
}
// to read data from server
InputStream input = s.getInputStream();
InputStreamReader isr = new InputStreamReader(input);
BufferedReader br = new BufferedReader(isr);
String data = null;
while ((data = br.readLine())!=null){
// Print it using sysout, or do whatever you want with the incoming data from server
}
}
}
服务器端代码
public class ServerTest {
ServerSocket s;
public void go() {
try {
s = new ServerSocket(44457);
while (true) {
Socket incoming = s.accept();
Thread t = new Thread(new MyCon(incoming));
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
class MyCon implements Runnable {
Socket incoming;
public MyCon(Socket incoming) {
this.incoming = incoming;
}
@Override
public void run() {
try {
PrintWriter pw = new PrintWriter(incoming.getOutputStream(),
true);
InputStreamReader isr = new InputStreamReader(
incoming.getInputStream());
BufferedReader br = new BufferedReader(isr);
String inp = null;
boolean isDone = true;
System.out.println("TYPE : BYE");
System.out.println();
while (isDone && ((inp = br.readLine()) != null)) {
System.out.println(inp);
if (inp.trim().equals("BYE")) {
System.out
.println("THANKS FOR CONNECTING...Bye for now");
isDone = false;
s.close();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
try {
s.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new ServerTest().go();
}
}
关闭套接字流周围的任何输入流或输出流或读写器将关闭套接字,并暗示关闭其他流、读写器和写器
在套接字的生命周期中使用相同的流、读卡器和写卡器。所以我根本不能使用main类的acknowledgeClient()
?Socket的所有IO任务都是从ClientHandler
的线程中完成的吗?不是您编写它的方式。您可以在调用方法之前创建流,并将其传递给处理程序。通常,处理程序也会进行确认。否则,速度较慢的使用者可能会停止服务器接受任何新连接。请执行相同操作,谢谢…:-)我以为一旦调用了Socket的close()
,您就可以重新打开它,但我不知道它甚至适用于Socket流。这对我来说也是新的知识。多亏了你的问题,我在研究源代码时发现了这一点:)