I'm trying to connect a very simple java socket client to a QTcpServer. However, while it connects, I can't send messages to and from. I have also tried connecting the java client to a java server (works nicely) and the Qt server to a qt client (also works nicely). But mixing them somehow doesn't..
Here's the Java client:
public class SocketClient {
public static void main(String[] args) throws IOException {
String hostName = "10.57.140.129";
int portNumber = 2010;
try (
Socket kkSocket = new Socket(hostName, portNumber);
PrintWriter out = new PrintWriter(kkSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(kkSocket.getInputStream()));
) {
BufferedReader stdIn =
new BufferedReader(new InputStreamReader(System.in));
String fromServer;
String fromUser;
while ((fromServer = in.readLine()) != null) {
System.out.println("Server: " + fromServer);
if (fromServer.equals("Test recieved. KKTHXBYE"))
break;
fromUser = stdIn.readLine();
if (fromUser != null) {
System.out.println("Client: " + fromUser);
out.println(fromUser);
}
}
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + hostName);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to " +
hostName);
System.exit(1);
}
}
}
With the bits of the QTserver code that is relevant:
#include "socketserver.h"
SocketServer::SocketServer(QObject *parent) :
QTcpServer(parent) {
}
void SocketServer::StartServer(){
if(!this->listen(QHostAddress::Any, 2010)){
qDebug() << "Could not start server";
}else{
qDebug() << "Listening...";
}
}
void SocketServer::incomingConnection(qintptr socketDescriptor){
qDebug() << socketDescriptor << " Connecting...";
SocketThread *thread = new SocketThread(socketDescriptor,this);
connect(thread, SIGNAL(finished()),thread, SLOT(deleteLater()));
connect(thread, SIGNAL(newData(QByteArray)), this, SLOT(incomeData(QByteArray)));
thread->start();
}
void SocketServer::incomeData(QByteArray newData){
emit sendBack(newData);
}
Thread:
#include "socketthread.h"
SocketThread::SocketThread(qintptr ID, QObject *parent) :
QThread(parent) {
this->socketDescriptor = ID;
}
void SocketThread::run(){
//thread starts here
qDebug() << socketDescriptor << " Starting thread";
socket = new QTcpSocket();
if(!socket->setSocketDescriptor(this->socketDescriptor)){
emit error(socket->error());
return;
}
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()), Qt::DirectConnection);
qDebug() << socketDescriptor << " Client Connected";
writeBack("connected");
exec();
}
void SocketThread::readyRead(){
QByteArray incomeData = socket->readAll();
qDebug() << socketDescriptor << " Data in: " << incomeData;
emit newData(incomeData);
}
void SocketThread::writeBack(QByteArray Data){
socket->write(Data);
}
void SocketThread::disconnected(){
qDebug() << socketDescriptor << " Disconnected";
socket->deleteLater();
exit(0);
}
Like mentioned, the client connects, and these debug outputs are written:
924 Connecting...
924 Starting thread
924 Client Connected
But no matter what I try to write from the client, it never picks up on anything with the readyReady() function. Any ideas? Am I missing specific endings on the lines I'm writing? (I've tried \r\n and \0, they don't seem to do much)
It seems like you are using line-based processing in Java but not in C++:
in.readLine() vs. socket->readAll()
and
out.println(fromUser) vs. writeBack("connected");
The C++ just never sends a CR/LF, which is not a problem when the other end does not expect one -> readAll(). The Java side however does expect (and send) CR/LF because you use BufferedReader.readLine() and BufferedWriter.writeln().
Decide if you want line-based communication or not and then adapt the C++ or the Java side accordingly.
Related
I have a java program on a computer that is the server and a program on the esp that acts as a client. They both connect to the local wifi and then to each other. The purpose is to have the computer send a number to the esp. I had managed to make them work, but then suddenly esp has stopped connecting to the server. I have spent quite some time trying to figure out what happened but I don't think I have changed anything. One day they all worked together, the next they didn't.
This is the main of my java code and I believe it works, even though it's probably not ideal (apart from this there are a couple of functions to make a small GUI and to do some actions):
createGUI();
//looking for the arduino port, to get data from it
SerialPort comPort = findArduinoPort();
if (comPort != null) {
System.out.println("Arduino port found: " + comPort.getSystemPortName());
} else {
System.out.println("Arduino port not found");
System.exit(0);
}
comPort.openPort();
comPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, 0, 0);
InputStream inComPort = comPort.getInputStream();
ServerSocket listener = new ServerSocket(8020);
char lastRead;
String data = new String("0");
try{
while(true){
Thread.sleep(0);
if(myStatus == status.ON) {
//read data from aduino serial
if (inComPort.available() > 0) {
data = "";
while (true) {
lastRead = (char)inComPort.read();
if (lastRead == '\r') {
lastRead = (char)inComPort.read();
break;
} else {
data += lastRead;
}
}
}
System.out.println("Waiting for client");
//from my understanding the next line waits for the client to connect
Socket socket = listener.accept();
socket.setKeepAlive(true);
System.out.println("Client Connected");
try{
//i read data from the client, to make sure it's ready to receive
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("Client response: " + in.readLine());
//I send the data to esp8266
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
System.out.println("Sending Message: " + data);
out.write(data);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
socket.close();
}
}
}
} finally {
try {
inComPort.close();
} catch (Exception e) {
e.printStackTrace();
}
comPort.closePort();
listener.close();
}
}
After writing to console "Waiting for client" it waits for a client to connect (and to my understanding it works fine). The problem comes with the code in esp8266
#include <ESP8266WiFi.h>
#include <LiquidCrystal.h>
//wifi data
#define NAME "i_put_my_wifi_here"
#define PASSWORD "i_put_my_wifi_pw_here"
String host = "i_put_my_computer_ip_here";
const int port = 8020;
WiFiClient client;
//lcd display to write the data to
LiquidCrystal lcd(D2, D3, D5, D6, D7, D8);
void setup() {
Serial.begin(115200);
//lcd setup
lcd.begin(16, 2);
lcd.print("Puntamenti:");
lcd.setCursor(0, 1);
lcd.print("0");
WiFi.mode(WIFI_STA);
WiFi.begin(NAME, PASSWORD);
Serial.print("\nConnecting to wifi");
while(WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("Connected\n");
}
void loop() {
//i try to conect to the server
if (client.connect(host, port))
{
Serial.print("Connected to host: ");
Serial.println(host);
//i tell the server i'm ready for data
client.println("Connected");
Serial.print("Wating for data");
int i = 0;
while(true){
if(client.available() == 0){
Serial.print(".");
i++;
if(i >= 10){
break;
}
delay(1000);
} else {
lcd.setCursor(0, 1);
String streamData = client.readStringUntil('\n');
lcd.print(streamData);
Serial.print("\nData received: ");
Serial.println(streamData);
break;
}
}
client.stop();
} else {
Serial.println("Connection to host failed");
}
delay(1000);
}
So my problem comes with client.connect(host, port). Last time i tried the programs it worked fine. It returned true and the rest would happen. Since today, however it's always false, so esp connects to the wifi, like the computer, but then it always fails to connect to the server waiting for it. I can't understand where's the problem, and especially how it can be that it used to work well and now it doesn't anymore.
Well, this is awkward. After spending a day on this I restarted my modem and now it works fine, just like before.
Alright, thanks anyway guys
I implemented a simple bi-directional pipe server in Java using JNA, respectively a client in Powershell.
Basically, I expect the client to connect, send a message to the server and finally get a message back from the server.
The actual results are different though. When I run the server first and then the client, the client waits forever to connect, while the server connects and then waits to read the message from the pipe.
The code in Java for the server, respectively the code in Powershell for the client can be seen below.
Any idea how to solve this issue?
Thanks!
static final int MAX_BUFFER_SIZE = 1024;
static String pipeName = "\\\\.\\pipe\\testpipe";
static HANDLE namedPipe;
public static void main(final String[] args) {
createPipe();
runServerFile();
}
private static void createPipe() {
namedPipe = INSTANCE.CreateNamedPipe(pipeName,
WinBase.PIPE_ACCESS_DUPLEX , // dwOpenMode
WinBase.PIPE_TYPE_BYTE | WinBase.PIPE_READMODE_BYTE | WinBase.PIPE_WAIT,// | WinBase.PIPE_READMODE_MESSAGE | WinBase.PIPE_TYPE_MESSAGE, // dwPipeMode
WinBase.PIPE_UNLIMITED_INSTANCES , // nMaxInstances,
//WinBase.PIPE_UNLIMITED_INSTANCES, // nMaxInstances (255),
Byte.MAX_VALUE, // nOutBufferSize,
Byte.MAX_VALUE, // nInBufferSize,
1000, // nDefaultTimeOut,
null); // lpSecurityAttributes
System.out.println("Created pipe: " + namedPipe.toString() + " invalid_handle = " + WinBase.INVALID_HANDLE_VALUE.toString());
System.out.println("Last error: " + Native.getLastError());
}
private static void runServerFile() {
RandomAccessFile npipeClient = null;
try {
System.out.println("br1");
npipeClient = new RandomAccessFile(pipeName, "rws");
INSTANCE.ConnectNamedPipe(namedPipe,null);
byte[] buffer = new byte[100];
int rd_count;
String recv;
System.out.println("Connected pipe");
do{
System.out.println("Before read");
rd_count = npipeClient.read(buffer);
if(rd_count<0) break;
System.out.println("After read");
recv = new String(buffer,0, rd_count);
System.out.println("Received" + recv);
}while(!recv.equalsIgnoreCase("done"));
System.out.println("Received correct message");
//npipeClient.write("Hello world!".getBytes());
npipeClient.writeUTF("Hello back!");
//npipeClient.getFD().sync();
//INSTANCE.FlushFileBuffers(new HANDLE(npipeClient.getFD().));
System.out.println("Sent: Hello back");
npipeClient.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
param ($ComputerName = '.')
$npipeClient = new-object System.IO.Pipes.NamedPipeClientStream($ComputerName, 'testpipe', [System.IO.Pipes.PipeDirection]::InOut,
[System.IO.Pipes.PipeOptions]::None,
[System.Security.Principal.TokenImpersonationLevel]::Impersonation)
$pipeReader = $pipeWriter = $null
function WriteToPipeAndLog($msg) {
$msg
$pipeWriter.WriteLine($msg)
}
try {
'Client connecting to sever'
$npipeClient.Connect()
'Connected to server'
$pipeReader = new-object System.IO.StreamReader($npipeClient)
$pipeWriter = new-object System.IO.StreamWriter($npipeClient)
$pipeWriter.AutoFlush = $true
Write-Host "Sent: Hello world!"
$pipeWriter.WriteLine('Hello world!')
$pipeWriter.WriteLine('How ya doing')
$pipeWriter.WriteLine('Done')
while (($line = $read.ReadLine()) -ne $null)
{
Write-Host "Received: " $line
}
}
finally {
'Client exiting'
$npipeClient.Dispose()
}
So I want to have a TCP connection between a Java client and a C++ server. Think of the client as an input device and the C++ server should receive JSON objects, parse them and use them in a game.
It seems like the connection is established successfully, but 1) there is an error("parse error-unexpected ''") when I try to parse the json objects (i'm using nlohmann's json) and 2) when I don't even call doStuff a.k.a just print out the buffer, only weird characters are printed (e.g.).
I assume I messed up something in the sending/receiving of data(This is the first time I use C++), but I've lost two days and really can't figure it out!
In the Java client I have:
private void connect() {
try {
hostname = conn.getHostname();
portnumber = conn.getPortNr();
socket = new Socket(hostname, portnumber);
out = new OutputStreamWriter(socket.getOutputStream());
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (Exception e) {
e.printStackTrace();
Log.e(debugString, e.getMessage());
}
}
public void sendMessage(String json) {
try {
//connect();
out.write(json.length());
Log.d(debugString, String.valueOf(json.length()));
out.flush();
out.write(json);
out.flush();
Log.d(debugString, json);
in.read();
this.close();
} catch (Exception e) {
e.printStackTrace();
Log.e(debugString, e.getMessage());
}
}
And in the C++ server:
void Server::startConnection() {
if (listen(s, 1) != 0) {
perror("Error on listen");
exit(EXIT_FAILURE);
}
listen(s, 1);
clilen = sizeof(cli_addr);
newsockfd = accept(s, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
close(newsockfd);
perror("Server: ERROR on accept");
exit(EXIT_FAILURE);
}
puts("Connection accepted");
int numbytes;
char buffer[MAXDATASIZE];
while (1)
{
numbytes = recv(s,buffer,MAXDATASIZE-1,0);
buffer[numbytes]='\0';
//Here's where the weird stuff happens
//cout << buffer;
//doStuff(numbytes,buffer);
if (numbytes==0)
{
cout << "Connection closed"<< endl;
break;
}
}
}
bool Server::sendData(char *msg) {
int len = strlen(msg);
int bytes_sent = send(s,msg,len,0);
if (bytes_sent == 0) {
return false;
} else {
return true;
}
}
void Server::doStuff(int numbytes, char * buf) {
json jdata;
try {
jdata.clear();
jdata = nlohmann::json::parse(buf);
if (jdata["type"] == "life") {
life = jdata["value"];
puts("json parsed");
}
} catch (const std::exception& e) {
cerr << "Unable to parse json: " << e.what() << std::endl;
}
}
Since your char "buffer" is showing weird characters after recv() on the C++ server it seems to me the issue should be due to character encoding mismatch between the Java client and the C++ server. To verify you can check the "numbytes" returned by recv() on C++ server, it should be greater than the number of characters in the JSON string on the Java client.
You are sending the lower 8 bytes of the JSON length but you're never doing anything about it at the receiver. This is almost certainly a mistake anyway. You shouldn't need to send the length. JSON is self-describing.
I want an android app and Windows C++ winsock to communicate using TCP sockets and I successfully sent a string from android to the C++ server but I cannot send string the other way around (from C++ server to Android client).
Here is the important C++ server part:
recvbuf = "Back At u \0";
cout << " \n " << recvbuf << "\n";
int iResult= send(ClientSocket, recvbuf, (int) strlen(recvbuf), 0);
if (iResult == SOCKET_ERROR) {
wprintf(L"send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %d\n", iResult);
And here is the android client recieving part:
class TextRcv extends AsyncTask<Void, Void, String>
{
#Override
protected String doInBackground(Void... params) {
//TO SEND A STRING
Socket clientSocket = null;
try {
clientSocket= new Socket("192.168.1.5",8889);
DataOutputStream oos= new DataOutputStream(clientSocket.getOutputStream());
oos.writeBytes(String.valueOf(mystr.length()));
oos.flush();
byte[] bufferout=mystr.getBytes();
oos.write(bufferout, 0, bufferout.length);
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
//to recieve a string
String input =null;
char[] buffin=new char[128];
try {
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
in.read(buffin, 0, 128);
input=String.valueOf(buffin);
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
return input;
}
#Override
protected void onPostExecute(String input) {
super.onPostExecute(input);
Toast toast=Toast.makeText(getApplicationContext(),input,Toast.LENGTH_LONG);
toast.show();
}
}
The C++ output says that there is no error and that 11 bytes (length of the recvbuff string) are sent. But on the android the 'input' string is always null.
Here is the c++ server output:
Start Receving
length of string recieved in bytes =14
AndroidID - Hello World...
Done
Back At u
Bytes Sent: 11
Press any key to continue . . .
String input =null;
At this point input is null.
char[] buffin=new char[128];
try {
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
in.read(buffin, 0, 128);
input=String.valueOf(buffin);
This code is not correct, but if it executes at all, input cannot possibly be null. The correct code is as follows:
int count = in.read(buffin);
if (count > 0)
{
input = new String(buffin, 0, count);
}
Back to your code:
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
return input;
If input is still null at this point, there must have been an IOException which you haven't disclosed.
I'm trying to test a Multi threaded TCP MuxServer in Java with a TCP client coded in C. below the code of the part which manages the communication with the client:
class Echo_TCP_Thread extends Thread
{
Socket Sock_Thr;
public Echo_TCP_Thread (Socket The_Socket)
{
this.Sock_Thr = The_Socket;
}
public void run()
{
try
{
PrintWriter output = new PrintWriter(Sock_Thr.getOutputStream());
InputStreamReader input = new InputStreamReader(Sock_Thr.getInputStream());
BufferedReader binput = new BufferedReader(input);
//
System.out.println ("Test 1"); //This message is displayed
//
String temp;
while ((temp=binput.readLine()) != null)
{
//
System.out.println ("Test 2"); //This message is not displayed
//
output.print(this.getName() + " answer -> ");
output.println(temp);
output.flush();
System.out.println ("Child Server : " + Thread.currentThread()
+ " has received" + temp);
}
}
catch (Exception e)
{
return;
}
finally
{
try
{
Sock_Thr.close();
System.out.println
("Child Server " + Thread.currentThread() + " : End !!! ");
}
catch (IOException e)
{
}
}
}
}
Even if I get connectivity and the end message is displayed in the client when I finish the communication, the client doesn't receive the echo messages from the server. I have checked with the Test messages that the program is not going into the while ((temp=binput.readLine()) != null) loop, but the message Test 1 is displayed right after I get connected to the server. What should I code to correct this?