Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java中的永久和持久套接字连接_Java_Sockets - Fatal编程技术网

java中的永久和持久套接字连接

java中的永久和持久套接字连接,java,sockets,Java,Sockets,我创建了一个客户端-服务器连接,类似于聊天系统。以前,我在客户端使用while循环,它每次都在等待从控制台读取消息(当然服务器也有while循环,可以永远服务)。但是现在,我试图首先在会话开始时创建一个连接,然后在会话期间偶尔发送一条消息,以保持永久和持久的连接 目前,如果没有while循环,客户端将关闭连接,我不知道如何找到解决方法 以下是客户端代码: import java.net.*; import java.io.*; public class ControlClientTest {

我创建了一个客户端-服务器连接,类似于聊天系统。以前,我在客户端使用
while
循环,它每次都在等待从控制台读取消息(当然服务器也有
while
循环,可以永远服务)。但是现在,我试图首先在会话开始时创建一个连接,然后在会话期间偶尔发送一条消息,以保持永久和持久的连接

目前,如果没有
while
循环,客户端将关闭连接,我不知道如何找到解决方法

以下是客户端代码:

import java.net.*;
import java.io.*;
public class ControlClientTest {
    private Socket socket = null;
//  private BufferedReader console = null;  
    private DataOutputStream streamOut = null;

    public static void main(String args[]) throws InterruptedException {
        ControlClientTest client = null;

        String IP="127.0.0.1";
        client = new ControlClientTest(IP, 5555);
    }

    public ControlClientTest(String serverName, int serverPort) throws InterruptedException {
        System.out.println("Establishing connection. Please wait ...");
        try {
            socket = new Socket(serverName, serverPort);
            System.out.println("Connected: " + socket);
            start();
        } catch (UnknownHostException uhe) {
            System.out.println("Host unknown: " + uhe.getMessage());
        } catch (IOException ioe) {
            System.out.println("Unexpected exception: " + ioe.getMessage());
        }

        String line = "";
//      while (!line.equals(".bye")) {
            try {
                Thread.sleep(1000);
                //TODO get data from input
//              line = console.readLine();
                line="1";
                if(line.equals("1"))
                    line="1,123";
                streamOut.writeUTF(line);
                streamOut.flush();
            } catch (IOException ioe) {
                System.out.println("Sending error: " + ioe.getMessage());
            }
//      }
    }

    public void start() throws IOException {
//      console = new BufferedReader(new InputStreamReader(System.in));
        streamOut = new DataOutputStream(socket.getOutputStream());
    }

}
以下是服务器代码:

import java.awt.*;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class ControlServer {
    private Socket socket = null;
    private ServerSocket server = null;
    private DataInputStream streamIn = null;

    public static void main(String args[]) {

        ControlServer server = null;
        server = new ControlServer(5555);
    }

    public ControlServer(int port) {
        try {
            System.out
            .println("Binding to port " + port + ", please wait  ...");
            server = new ServerSocket(port);
            System.out.println("Server started: " + server);
            System.out.println("Waiting for a client ...");
            socket = server.accept();
            System.out.println("Client accepted: " + socket);
            open();
            boolean done = false;
            while (!done) {
                try {
                    String line = streamIn.readUTF();
                    // TODO get the data and do something
                    System.out.println(line);

                    done = line.equals(".bye");
                } catch (IOException ioe) {
                    done = true;
                }
            }
            close();
        } catch (IOException ioe) {
            System.out.println(ioe);
        }

    }


    public void open() throws IOException {
        streamIn = new DataInputStream(new BufferedInputStream(
                socket.getInputStream()));
    }
public void close() throws IOException {
    if (socket != null)
        socket.close();
    if (streamIn != null)
        streamIn.close();
}

}

您可以在连接周围缠绕一个线程,让它定期发送状态以保持线路畅通,比如说每30秒或其他任何时间。然后,当它实际有数据要发送时,它会将保持活动重置为上次传输后的30秒。该状态可能有助于查看客户端是否仍然处于活动状态,因此至少它是一个有用的ping


此外,您还应该更改服务器代码,因为此时您似乎只处理一个连接。您应该循环,当套接字连接进入时,生成一个线程来处理客户机请求并返回侦听。不过,我可能正在深入阅读您的测试代码。

将客户端套接字连接包装在线程上。使用等待消息。整个应用程序中应该只有一个发送方队列,所以请使用单例模式

e、 g

当需要向服务器发送消息时,可以使用阻塞队列发送消息

QueueSingleton queue = QueueSingleton.getSenderQueue();
queue.put(message)
客户端线程将唤醒并处理消息

QueueSingleton queue = QueueSingleton.getSenderQueue();
queue.put(message)
要保持连接,请使用。这是一种特殊类型的线程,在指定的时间段内重复调用run方法。你可以经常用它来发布一条消息,一条ping消息


为了处理接收到的消息,您可以有另一个线程,在另一个阻塞队列(接收方队列)上等待消息。客户端线程将把收到的消息放在这个队列上。

我想总结一些关于TCP/IP连接稳定性的好做法,我每天都会应用这些做法

良好做法1:内置保持活力 它会在一段时间不活动后自动发送信号,并检查是否有回复。不过,保持活动时间间隔取决于操作系统,并且有一些缺点。但总的来说,它可以提高你的连接的稳定性

良好做法2:暂停 当您执行
读取
(或者在您的情况下执行
readUTF
)时,您的线程实际上将永远阻塞。根据我的经验,这是一种糟糕的做法,原因如下:很难关闭应用程序。只调用
socket.close()
是脏的

一种干净的溶液,是一种简单的读取超时(例如200ms)。您可以使用
设置otimeout
方法执行此操作。当
read()
方法超时时,它将抛出一个
SocketTimeoutException
。(它是
IOException
的子类)

下面是一个实现循环的示例。请注意
关闭
情况。只要将它设置为真,你的线程就会和平地消亡

while (!shutdown)
{
  try
  {
    // some method that calls your read and parses the message.
    code = readData();
    if (code == null) continue; 
  }
  catch (SocketTimeoutException ste)
  {
    // A SocketTimeoutExc. is a simple read timeout, just ignore it.
    // other IOExceptions will not be stopped here.
  }
}
良好实践3:Tcp无延迟 当您经常与需要快速处理的小命令交互时,请使用以下设置

try
{
  socket.setTcpNoDelay(true);
}
catch (SocketException e)
{
}
良好实践4:心跳 事实上,还有很多副场景还没有涉及到

例如,其中一个是设计为一次仅与一个客户机通信的服务器应用程序。有时他们接受连接,甚至接受消息,但从不回复

另一个问题:有时候当你失去连接时,你的操作系统可能会花很长时间才会注意到这一点。可能是由于良好做法3中描述的缺点,但在更复杂的网络情况下(例如,使用RS232到以太网转换器、VMware服务器等),这种情况经常发生

这里的解决方案是创建一个线程,该线程每x秒发送一条消息,然后等待回复。(例如,每15秒一次)。为此,您需要创建第二个线程,每15秒发送一条消息。其次,您需要稍微扩展一下良好实践守则2

  try
  {
    code = readData();

    if (code == null) continue; 
    lastRead = System.currentTimeMillis();

    // whenever you receive the heart beat reply, just ignore it.
    if (MSG_HEARTBEAT.equals(code)) continue;

    // todo: handle other messages
  }
  catch (SocketTimeoutException ste)
  {
    // in a typical situation the soTimeout is about 200ms
    // the heartbeat interval is usually a couple of seconds.
    // and the heartbeat timeout interval a couple of seconds more.
    if ((heartbeatTimeoutInterval > 0) &&
        ((System.currentTimeMillis() - lastRead) > heartbeatTimeoutInterval))
    {
      // no reply to heartbeat received.
      // end the loop and perform a reconnect.
      break;
    }
  }

您需要决定您的客户机或服务器是否应该发送消息。这个决定并不重要。但是,例如,如果您的客户端发送消息,那么您的客户端将需要额外的线程来发送消息。服务器收到消息时应发送回复。当您的客户收到答案时,它应该只
继续
(即参见上面的代码)。双方都应该用一种非常相似的方式检查:“多久了?”你为什么不想要一个循环呢?嗯,对我来说太多新东西了。我真的不知道如何将它应用到我的代码中。每次我想发送东西时,我能创建一个新的套接字吗?这些东西不应该太多。也许3秒钟内就有3个,然后延迟1分钟。你可以,但这不是你要求的永久和持久的联系。嗯,对我来说太多新东西了。我真的不知道如何将它应用到我的代码中。每次我想发送东西时,我能创建一个新的套接字吗?这些东西不应该太多。3秒钟内可能有3个,然后延迟1分钟。太好了!谢谢你提供的细节。回答得非常好。如果您能推荐一些书籍或合适的网络资源来提高我对TCP/IP客户机/服务器连接的知识,我将不胜感激。@ThePlanman91大约10年前我读过《用Java思考》,读过《有效Java》的一些部分,并参加了OCJP测试。我也喜欢这篇关于编码和字符集的文章;我从未读过一本只涉及套接字的书。但是在stackoverflow上有很多问答;感谢@bvdb的回复。我现在很忙
try
{
  socket.setTcpNoDelay(true);
}
catch (SocketException e)
{
}
  try
  {
    code = readData();

    if (code == null) continue; 
    lastRead = System.currentTimeMillis();

    // whenever you receive the heart beat reply, just ignore it.
    if (MSG_HEARTBEAT.equals(code)) continue;

    // todo: handle other messages
  }
  catch (SocketTimeoutException ste)
  {
    // in a typical situation the soTimeout is about 200ms
    // the heartbeat interval is usually a couple of seconds.
    // and the heartbeat timeout interval a couple of seconds more.
    if ((heartbeatTimeoutInterval > 0) &&
        ((System.currentTimeMillis() - lastRead) > heartbeatTimeoutInterval))
    {
      // no reply to heartbeat received.
      // end the loop and perform a reconnect.
      break;
    }
  }