【问题标题】:How to implement TCP server in java and TCP Client in cpp to transfer string如何在java中实现TCP server和cpp中的TCP Client来传输字符串
【发布时间】:2016-11-14 19:59:08
【问题描述】:

我正在尝试将一条简单的消息从作为客户端的树莓派传输到作为服务器的计算机。我对 tcpClient 使用 cpp,对 tcpServer 使用 java。 这是我的 TCPServer.java:

import java.net.*;
import java.io.*;


class TCPServer extends Thread {

    TCPClass() {
    }

    public void connect(){
        try {
            ServerSocket welcomeSocket = new ServerSocket();
            welcomeSocket.setReuseAddress(true);
            welcomeSocket.bind(new InetSocketAddress(8080));

            System.out.println("server start listening... ... ...");

            Socket connectionSocket = welcomeSocket.accept();
            System.out.print("Server has connected!\n");
            Connection c = new Connection(connectionSocket);
            c.start();
            connectionSocket.close();
            welcomeSocket.close();
            System.out.println("connection terminated");
        }
        catch(IOException e) {
            System.out.println("Listen :"+e.getMessage());
        }
    }

    class Connection extends Thread{
        Socket connectionSocket;
        Connection(Socket _connectionSocket){
                connectionSocket = _connectionSocket;    
        }
        public void run(){
            try{
                BufferedReader inFromClient = new BufferedReader(new InputStreamReader (connectionSocket.getInputStream()));
                DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
                String clientSentence = inFromClient.readLine();
                System.out.println("Client sent: "+clientSentence);

String capitalizedSentence = clientSentence.toUpperCase() + '\n';

                System.out.println("Client sent: "+capitalizedSentence);
                outToClient.writeBytes(capitalizedSentence);
                outToClient.flush();
                inFromClient.close();
            }catch(Exception e){}
        }
    }

这是我的 TCPClient.cpp:

 #include "Client.h"
#include <QHostAddress>

Client::Client(QObject* parent): QObject(parent)
{
  connect(&client, SIGNAL(connected()),
    this, SLOT(startTransfer()));
}

Client::~Client()
{
  client.close();
}

void Client::start(QString address, quint16 port)
{
  QHostAddress addr(address);
  client.connectToHost(addr, port);
}

void Client::startTransfer()
{
  client.write("Hello, world", 13);
}

最后,这是执行我的 TCPClient.cpp 的程序:

#include "Client.h"
#include <QApplication>
#include <iostream>

int main(int argc, char** argv)
{
  QApplication app(argc, argv);

  Client client;
  std::cout << argv[1] << " " << argv[2] << std::endl;
  client.start( argv[1], atoi( argv[2] ) );
//  client.start("127.0.0.1", 8888);

  return app.exec();
}

所以我执行了我的 TCPServer.java,我有一条消息证明服务器已经连接,所以我执行了我的 TCPCLient.cpp ,并且出现了问题。我的服务器没有显示客户端发送的任何消息,但是当我结束 TCPClient.cpp 的执行时,该消息显示在我的屏幕上,这意味着服务器已收到该消息。奇怪没有!! 谢谢你的帮助。

编辑: 这是我的 Client.h,抱歉耽搁了

// client.h
#include <QtNetwork>
#include <QObject>
#include <QString>
#include <QTcpSocket>

class Client: public QObject
{
Q_OBJECT
public:
  Client(QObject* parent = 0);
  ~Client();
  void start(QString address, quint16 port);
public slots:
  void startTransfer();
private:
  QTcpSocket client;
};

【问题讨论】:

    标签: java c++ sockets tcp


    【解决方案1】:

    一点也不。您正在使用以下方法关闭服务器中的套接字:

    connectionSocket.close();
    

    就在启动线程之后。因此,当线程开始执行时,它将与关闭的套接字一起工作。请记住,start() 不会等待线程终止(它会在线程创建后立即返回)。在关闭所有内容之前,您必须让TcpServer 等待Connection 线程的终止。像这样更改代码:

     Connection c = new Connection(connectionSocket);
     c.start();
     c.join();  //add this line. It means: wait for the termination of c then proceed to closing the socket
     connectionSocket.close();
    

    [更新]

    另外,你需要在写入后刷新客户端(cpp部分):

    client.write("Hello, world", 13);
    client.flush();
    

    【讨论】:

    • 谢谢你的想法,我按照你说的改了代码,还是不行:/
    • 不幸的是还是同样的问题,这让我抓狂
    • 您客户的逻辑有问题。您调用默认构造函数,但您的类没有when。在构造函数中,连接客户端套接字并指定在连接成功时调用startTransfer()。但是您直到稍后才指定地址和端口(通过调用start(...))。因此,您可以在指定地址之前开始传输。我认为对connect(&amp;client, ... 的调用应该转移到调用client.start(... 之后调用的方法。无论如何,我的回答中的修改也是必要的。
    • 你能澄清一下吗
    • 告诉我们Client.h,我会在上面的答案中添加修改。
    【解决方案2】:

    您永远不会等待对等方能够发送任何内容,然后立即关闭连接,服务器端和客户端。在这样的用例中,您应该使用纸和铅笔来写下您想要的:

    • 服务器监听 - 等待连接
    • 客户端连接 - 服务器接受并读取一行 -> 服务器等待输入数据
    • 客户端发送一条线并等待确认 -> 客户端等待输入数据
    • 服务器发送大写行(即使它会被忽略)并表示它已经完成了shutdown write不是关闭) - 再次它应该等待一个确认 并等待输入数据
    • 关闭会导致客户端在读取所有答案后读取长度为 0

    您现在确定从一侧发送的所有数据都已被对等方接收:客户端可以安全地关闭其套接字。服务器将读取 0 长度并关闭自己的套接字

    这称为graceful shutdown,并保证在 TCP 连接断开之前,对等方已接收到由一侧发送的所有内容。

    【讨论】:

    • 服务器端调用inFromClient.readLine()被阻塞。因此,服务器实际上在等待对等方。虽然客户端没有读取服务器的响应(大写字符串),但我不认为这可能是问题。
    • 所以我必须调用 inFromClient.shutdown() 而不是 close??
    猜你喜欢
    • 2016-08-26
    • 2011-06-07
    • 2013-03-02
    • 2011-12-18
    • 1970-01-01
    • 2019-11-03
    • 2014-02-28
    • 2021-02-03
    • 1970-01-01
    相关资源
    最近更新 更多