1

Im trying to transfer a simple message from my raspberry pi which is the client to my computer which is the server. Im using cpp for tcpClient and java for tcpServer. This is the my 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){}
        }
    }

This is my 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);
}

and finally, this is the program which executes my 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();
}

so I execute my TCPServer.java, I have a message to prove that the server has connected, so I execute my TCPCLient.cpp , and there is a problem. My server doesn't show any message sent by the client, but when I end the execution of my TCPClient.cpp , the message is shown on my screen which means the server has received the message. Weird no!! Thank you for the help.

EDIT: This is my Client.h, sorry for the delay

// 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;
};

2 Answers 2

3

Not at all. You are closing the socket in the server using:

connectionSocket.close();

just after starting the thread. So, when the thread starts execution, it would work with a closed socket. Remember that start() does not wait for the termination of the thread (it returns immediately after thread creation). You have to let TcpServer wait for the termination of Connection thread before closing everything. Change the code like this:

 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();

[Update]

Also, you need to flush the client (cpp part) after writing:

client.write("Hello, world", 13);
client.flush();
Sign up to request clarification or add additional context in comments.

7 Comments

Thank you for your idea, I changed my code like you said, still doesn't work :/
Unfortunately still the same problem, this is driving me crazy
There is something wrong with your client's logic. You call the default constructor, but your class does not have when. In the constructor, you connect the client socket and specify startTransfer() to be called when the connection succeeds. But you don't specify the address and the port until later (by calling start(...)). So, it is possible that you start transfer before specifying the address. I think that the call to connect(&client, ... should be moved to a method that is called after calling client.start(.... Anyway, the modifications in my answer are also necessary.
Can you clarify please
Show us Client.h and I will add the modifications to my answer above.
|
0

You never wait from the peer to be able to send anything, and immediately close the connection, server side and client side. In a use case like that, you should use a paper and pencil to just write what you want:

  • server listens - waits for a connection
  • client connect - server accept and read a line -> server waits for input data
  • client sends a line and should wait for an acknowledgement -> client shall wait for input data
  • server sends the upper cased line (even if it will be ignored) and signals that it has finished with a shutdown write (not a close) - again it shall wait for an acknowledgment and as such wait for input data
  • the shutdown causes the client to have a 0 length read when it has read all the answer

You are now sure that all the data that has been sent from one side has been received by the peer: the client can safely close its socket. The server will get a 0 length read and will close its own socket

This is called a graceful shutdown and guarantees that everything that was sent by one side has been received by the peer before the TCP connection is broken.

2 Comments

The call inFromClient.readLine() in the server side is blocking. So, the server actually waits for the peer. Although the client does not read the server's response (capitalized string), I don't think that this could be the problem.
So I have to call inFromClient.shutdown() instead of close??

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.