I am trying to build an android app that communicates with a c++ server running on windows using TCP sockets. I successfully sent a string from the app to the server but I cannot do the other way around. Please help me because I have been trying with this issue for a while now.
Android Client:
String mystr="Hello World...";
char[] buffin=new char[128];
String input =null;
Integer count = 0;
class TextRcv extends AsyncTask<Void, Void, Integer>
{
#Override
protected Integer doInBackground(Void... params) {
//Sending a string (WORKING)
Socket clientSocket = null;
try {
clientSocket= new Socket("192.168.1.5",8889);
DataOutputStream oos= new DataOutputStream(clientSocket.getOutputStream());
oos.writeBytes(mystr);
//oos.writeBytes(String.valueOf(mystr.length()));//write the length of the string first
//byte[] bufferout=mystr.getBytes();
//oos.write(bufferout, 0, bufferout.length);
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
//Recieving a String (Not working)
try {
BufferedReader in = null;
if (clientSocket != null)
{
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
else
{
Log.e("samer ","CLIENTSOCKET NULL");
}
if (in != null)
{
count=in.read(buffin);
}
else
{
Log.e("samer ","BUFFERREADER NULL");
}
if(count>0)
{
input=new String(buffin,0,count);
}
if (clientSocket != null) {
clientSocket.close();
}
} catch (IOException e) {
Log.i("samer count: ",String.valueOf(count));//RETURNS 0 !!
Log.i("buff samer: ", String.valueOf(buffin));//Returns garbage
e.printStackTrace();
}
return count;
}
#Override
protected void onPostExecute(Integer count) {
super.onPostExecute(count);
Toast toast=Toast.makeText(getApplicationContext(),String.valueOf(count),Toast.LENGTH_LONG);
toast.show();
}
}
The 'count' always returns 0 despite the fact that on the windows c++ server side it says that it has successfully sent the 25 bytes.
C++ Winsock Server:
int main(int argc, const char *argv[])
{
WSADATA wsaData;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int valread;
int iSendResult;
char * recvbuf;
char *recvstr;
int recvbuflen = DEFAULT_BUFLEN;
recvbuf = (char*)malloc((recvbuflen + 1) * sizeof(char));
recvstr = (char*)malloc((recvbuflen + 1) * sizeof(char));
char* AndroidID;
char *sendbuf = "Client: sending data test";
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Setup the TCP listening socket
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
if (ClientSocket != INVALID_SOCKET)
{
cout << "Start Receving" << endl;
//------Start Receiving
//-----------------------------------
int lengthofrecv=recv(ClientSocket, recvbuf, recvbuflen, 0);
recvbuf[lengthofrecv] = '\0';//append \0 to use with printf()
AndroidID = recvbuf;
printf("AndroidID - %s \n", recvbuf);
cout << " \n Done ";
//---Start Sending to android
//-----------------------------------------
iResult = send(ClientSocket, sendbuf, (int)strlen(sendbuf), 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);
cout << WSAGetLastError() << endl;
}
// shutdown the connection since we're done
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
//cleanup
closesocket(ClientSocket);
WSACleanup();
return 0;
}
Server console output:
Start Receving
AndroidID - Hello World...
Done Bytes Sent: 25
0
Press any key to continue . . .
The problem is that you are calling oos.close() after sending the initial string to the server.
DataOutputStream extends FilterOutputStream, and the behavior of its close() method is documented:
FilterOutputStream.close()
The close method of FilterOutputStream calls its flush method, and then calls the close method of its underlying output stream.
In this case, the "underlying output stream" is the socket's outputStream, and its close() behavior is also documented:
Socket.getOutputStream()
Closing the returned OutputStream will close the associated socket.
Socket.close()
Closes this socket.
Any thread currently blocked in an I/O operation upon this socket will throw a SocketException.
Once a socket has been closed, it is not available for further networking use (i.e. can't be reconnected or rebound). A new socket needs to be created.
Closing this socket will also close the socket's InputStream and OutputStream.
If this socket has an associated channel then the channel is closed as well.
So, your client is closing the socket connection before it can read the server's reply string. You need to remove that call to oos.close() so yo keep the connection open until you are done reading.
On the server side, simply due to timing, your code may be able to call send() and put the reply string into the socket's outbound buffer before the socket detects the disconnect. The buffer is not actually transmitted by send() itself, it is queued to the OS kernel, which will transmit the data in the background. So send() will return success instead of failure if the reply string is buffered before the disconnect is detected.
Related
I have been working on a java program that basically acts like Minechat(text-based app to just view chat.) I have never really worked with networking too much, so the issue is figuring out how to send packets correctly. I am currently at the position of creating the handshake with the server. After hours of research, I have come up with the following code, but it always runs into the "Failed! (Exception)" message. To me, everything looks correct, but for all I know it could be 100% wrong. If someone could point out what I'm doing wrong here, I'd really appreciate it.
For reference, feel free to use this and this.
public static void main(String[] args) throws IOException {
host = new InetSocketAddress("162.244.165.111", 48040);
socket = new Socket();
System.out.println("Connecting...");
socket.connect(host, 3000);
System.out.println("Done!");
System.out.println("Making streams...");
output = new DataOutputStream(socket.getOutputStream());
input = new DataInputStream(socket.getInputStream());
System.out.println("Done!");
System.out.println("Attempting handshake... "+host.getAddress().toString().substring(1));
byte[] msg = ("47;"+host.getAddress().toString().substring(1)+";"+host.getPort()+";2;").getBytes(Charset.forName("UTF-16"));
output.writeInt(msg.length+Integer.valueOf(0x00));
output.writeByte(0x00);
output.write(msg);
output.flush();
try {
if (input.readByte() != 0x02)
System.out.println("Failed!");
else
System.out.println("Done!");
} catch (EOFException e) {
System.out.println("Failed! (Exception)");
}
}
EDIT:
More research suggests I use a Byte array, but this confuses me on how to represent a string and using strings is required?
Looking at this page http://wiki.vg/Protocol it looks like your not writing enough data nor in the right order. You also need to be using varint which is a special type of data representation of an integer.
Relevant links to this issue:
Handshake Protocol
Packet format
Server Ping Explanation and Example (which involves handshake)
The status ping works as follows:
C->S : Handshake State=1
C->S : Request
S->C : Response
C->S : Ping
S->C : Pong
C is client and S is server
Using the wiki and the provided code samples I modified your code to follow the entire status request.
public static void main(String [] args) throws IOException {
String address = "162.244.165.111";
int port = 48040;
InetSocketAddress host = new InetSocketAddress(address, port);
Socket socket = new Socket();
System.out.println("Connecting...");
socket.connect(host, 3000);
System.out.println("Done!");
System.out.println("Making streams...");
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
DataInputStream input = new DataInputStream(socket.getInputStream());
System.out.println("Done!");
System.out.println("Attempting handshake... "+host.getAddress().toString());
byte [] handshakeMessage = createHandshakeMessage(address, port);
// C->S : Handshake State=1
// send packet length and packet
writeVarInt(output, handshakeMessage.length);
output.write(handshakeMessage);
// C->S : Request
output.writeByte(0x01); //size is only 1
output.writeByte(0x00); //packet id for ping
// S->C : Response
int size = readVarInt(input);
int packetId = readVarInt(input);
if (packetId == -1) {
throw new IOException("Premature end of stream.");
}
if (packetId != 0x00) { //we want a status response
throw new IOException("Invalid packetID");
}
int length = readVarInt(input); //length of json string
if (length == -1) {
throw new IOException("Premature end of stream.");
}
if (length == 0) {
throw new IOException("Invalid string length.");
}
byte[] in = new byte[length];
input.readFully(in); //read json string
String json = new String(in);
// C->S : Ping
long now = System.currentTimeMillis();
output.writeByte(0x09); //size of packet
output.writeByte(0x01); //0x01 for ping
output.writeLong(now); //time!?
// S->C : Pong
readVarInt(input);
packetId = readVarInt(input);
if (packetId == -1) {
throw new IOException("Premature end of stream.");
}
if (packetId != 0x01) {
throw new IOException("Invalid packetID");
}
long pingtime = input.readLong(); //read response
// print out server info
System.out.println(json);
System.out.println("Done!");
}
public static byte [] createHandshakeMessage(String host, int port) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
DataOutputStream handshake = new DataOutputStream(buffer);
handshake.writeByte(0x00); //packet id for handshake
writeVarInt(handshake, 4); //protocol version
writeString(handshake, host, StandardCharsets.UTF_8);
handshake.writeShort(port); //port
writeVarInt(handshake, 1); //state (1 for handshake)
return buffer.toByteArray();
}
public static void writeString(DataOutputStream out, String string, Charset charset) throws IOException {
byte [] bytes = string.getBytes(charset);
writeVarInt(out, bytes.length);
out.write(bytes);
}
public static void writeVarInt(DataOutputStream out, int paramInt) throws IOException {
while (true) {
if ((paramInt & 0xFFFFFF80) == 0) {
out.writeByte(paramInt);
return;
}
out.writeByte(paramInt & 0x7F | 0x80);
paramInt >>>= 7;
}
}
public static int readVarInt(DataInputStream in) throws IOException {
int i = 0;
int j = 0;
while (true) {
int k = in.readByte();
i |= (k & 0x7F) << j++ * 7;
if (j > 5) throw new RuntimeException("VarInt too big");
if ((k & 0x80) != 128) break;
}
return i;
}
i have a simple c server and java client implementation and i am testing the server for request handling. I am using executor service for simulating simultaneous requests.
Mechanism : The sever just reads a string from client and acknowledges it by sending back a message to the client.
Issue : For some requests the server doesn't get the message which was sent by the client.
C server:
#include <stdio.h>
#include <string.h> //strlen
#include <stdlib.h> //strlen
#include <sys/socket.h>
#include <arpa/inet.h> //inet_addr
#include <unistd.h> //write
#include <pthread.h> //for threading , link with lpthread
//the thread function
void *connection_handler(void *);
int main(int argc , char *argv[])
{
int socket_desc , client_sock , c;
struct sockaddr_in server , client;
static int client_count = 0;
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
printf("Could not create socket");
}
puts("Socket created");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 5000 );
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
//print the error message
perror("bind failed. Error");
return 1;
}
puts("bind done");
//Listen
listen(socket_desc , 1000);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
pthread_t thread_id;
while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
{
client_count++;
printf("Connection accepted for client no : %d\n",client_count);
if( pthread_create( &thread_id , NULL , connection_handler , (void*) &client_sock) < 0)
{
perror("could not create thread");
return 1;
}
//Now join the thread , so that we dont terminate before the thread
//pthread_join( thread_id , NULL);
puts("Handler assigned");
}
if (client_sock < 0)
{
perror("accept failed");
return 1;
}
return 0;
}
void *connection_handler(void *socket_desc)
{
//Get the socket descriptor
int sock = *(int*)socket_desc;
int read_size, t = 0, operation = -1, buffer_size = 0;
char *message , recv_meta[2000], *data[3];
//Receive a message from client
while(read_size = recv(sock, recv_meta, 2000, 0) > 0 ) {
printf("Meta from client : %s\n",recv_meta);
sprintf(recv_meta, "%s", "OK, Meta Data received!");
send(sock, recv_meta, strlen(recv_meta), 0); //send acknowledgement
}
if(read_size == 0)
{
puts("Client disconnected");
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
return 0;
}
Java Client:
import java.net.*;
import java.io.*;
import java.util.Arrays;
import java.util.concurrent.*;
public class client
{
public static void main(String[] args)
{
ExecutorService executorService = Executors.newFixedThreadPool(100);
for (int i = 0; i < 5; i++) {
Runnable worker = new WorkerThread(""+i);
executorService.execute(worker);
}
executorService.shutdown();
}
}
class WorkerThread implements Runnable {
String clientcount = "";
public WorkerThread(String s){
this. clientcount=s;
}
#Override
public void run() {
Socket socket = null;
int PORT = 5000, buffer_size = 0;
String meta = " ";
meta = "newfileidforenc:1:20000";
// Create the socket connection to the EchoServer.
try
{
socket = new Socket("localhost", PORT);
}
catch(UnknownHostException uhe)
{
// Host unreachable
System.out.println("Unknown Host");
}
catch(IOException ioe)
{
// Cannot connect to port on given host
System.out.println("Cant connect to server at port "+PORT+". Make sure it is running.");
return;
}
try
{
PrintWriter pout = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
BufferedReader pin = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pout.println(meta);
pout.flush();
System.out.println("\nServer Says : " + pin.readLine() + "for "+ clientcount);
}
catch(Exception ioe)
{
System.out.println("\nException during communication. Server probably closed connection.");
}
finally
{
try
{
// Close the socket before quitting
socket.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
Output : It is not the same. All the client gets connected and disconnect successfully. But the server doesn't receive and print the data from all the clients.
You have numerous problems with:
1) Not correctly handling TCP streams and assuming that TCP transfers messages instead of octet, (byte) streams.
2) Not appreciating the C-style null-terminated char arrays that msaquerade as a string type.
3) Passing values by address to thread create calls.
See comments.
I found a solution for the issue.
Actual issue : Executor service is used for load testing i.e., there would be more number of requests sent per second. Under such heavy load the code enters a race condition. The client_sock whose address is passed to the pthread_create() is being overwritten by the next accept() call before it is copied to the sock variable inside the connection_handler(). This leads to a scenario where a single connection would be processed by two or more threads and some other connections are left unhandled.
Solution : Copy the client_sock to a string buffer which should be passed as the argument for pthread_create().
Hope it will be useful.
I am trying to write a server-client application for file transfer. The client is written in Java and the server is written in C++.
Unfortunately I have the following error:
java.net.SocketException: Connection reset by peer: socket write error"
Here is my code for client:
import java.io.*;
import java.net.Socket;
public class Proba_binar
{
public static void main(String[] args)
{
byte[] buffer = null;
byte[] auxByte = new byte[1000];
String fileName = "1.jpg";
File a_file = new File(fileName);
try
{
// Create a socket
Socket socket = new Socket("192.168.14.146", 8888);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// Read file
FileInputStream fis = new FileInputStream(fileName);
int length = (int)a_file.length();
buffer = new byte[length];
fis.read(buffer);
fis.close();
// Send file length
System.out.println("length = " + Integer.toString(length));
out.write(Integer.toString(length) + "\n");
out.flush();
// Send file
int imageSize = buffer.length;
char[] auxChar = new char[1000];
int nr_transf = imageSize / 1000;
int rest_byte = imageSize % 1000;
System.out.println("nr_transf = " + nr_transf);
for(int j = 0; j < nr_transf; j++)
{
// send series of 1000 bytes
for(int i = 0; i < 1000; i++)
{
auxChar[i] = (char)buffer[j*1000+i];
auxByte[i] = buffer[j*1000+i];
}
out.write(auxChar);
out.flush();
}
// send last bytes
for(int i = 0; i < rest_byte; i++)
{
auxChar[i] = (char)buffer[1000*nr_transf+i];
auxByte[i] = buffer[1000*nr_transf+i];
}
out.write(auxChar, 0, rest_byte);
out.flush();
out.close();
in.close();
socket.close();
System.out.println("Transfer finished!");
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
And the code for server:
int main(int argc , char *argv[])
{
WSADATA wsa;
SOCKET s , new_socket;
struct sockaddr_in server , client;
int c, bytecount, nr_transf, rest_byte, i;
int recv_size, file_size;
char message[1000];
char buffer[1000];
int buffer_len = 1000;
FILE *f = fopen("out.jpg", "wb");
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.\n");
//Create a socket
if((s = socket(AF_INET, SOCK_STREAM, 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
getch();
return 0;
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
//Bind
if(bind(s, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d" , WSAGetLastError());
getch();
return 0;
}
puts("Bind done");
//Listen to incoming connections
listen(s, 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
new_socket = accept(s, (struct sockaddr*)&client, &c);
if (new_socket == INVALID_SOCKET)
{
printf("accept failed with error code : %d", WSAGetLastError());
getch();
return 0;
}
puts("Connection accepted");
//Receive FILE DIMENSION from client
if((recv_size = recv(new_socket, message, 1000, 0)) == SOCKET_ERROR)
{
puts("recv failed");
getch();
}
message[recv_size] = '\0';
file_size = atoi(message);
printf("\nfile_size = %d", file_size);
nr_transf = file_size / 1000;
rest_byte = file_size % 1000;
//Receive FILE from client
for(i = 0; i < nr_transf; i++)
{
// receive 1000 bytes
if((bytecount = recv(new_socket, buffer, buffer_len, 0)) == SOCKET_ERROR)
{
printf("Receive failed auxChar");
getch();
return 0;
}
fwrite(buffer, 1, buffer_len, f);
}
// receive last bytes
if((bytecount = recv(new_socket, buffer, rest_byte, 0)) == SOCKET_ERROR)
{
printf("Receive failed rest_byte");
getch();
return 0;
}
fwrite(buffer, 1, rest_byte, f);
fclose(f);
printf("Receive finished!");
closesocket(s);
WSACleanup();
getch();
return 0;
}
I made equivalent server in Java and works perfectly.
I do not know what the problem is in c + + version.
Thanks in advance!
recv() does not guarantee that it will read all bytes requested:
...calling recv will return as much data as is currently available—up to the size of the buffer specified...
This means that the for/recv loop is incorrectly structured and it is probably the case that the server believes it has read all the data but it has not. This results in the server closing the socket before the client has sent all the data, resulting in the error reported by the Java client.
Example (untested) restructuring of the recv loop:
int totalBytesRead = 0;
int bytesRead;
while (totalBytesRead < file_size)
{
if((bytesRead = recv(new_socket, buffer, buffer_len, 0)) == SOCKET_ERROR)
{
/* Handle failure. */
break;
}
if (bytesRead != fwrite(buffer, 1, bytesRead, f))
{
/* Handle failure. */
break;
}
totalBytesRead += file_size;
}
Remember that connected sockets are stream based, using mutilple send()s does not imply that the matching recv()s will read the data in the same "chunks" as they were sent. In addition to the data content retrieval error already mentioned, this equally applies to the reading of the file size. There is no guarantee that entire file size will be read.
I would recommend designing a simple protocol to ensure the different types of data are correctly read. For example, client sends:
<file_size>\n<file_content>
the server reads all data up to the newline character and converts it into the file size. The server then knows for certain it has the correct file size. The server then reads file_size bytes from the socket. Finally, server responds to indicate success or failure:
success\n
the client reads up to the newline character to obtain the response.
I'm having a problem trying to send strings back and forth between a simple Java socket client and a simple C socket server.
It works as follows:
Java client sends msg to C server
out.writeBytes(msg);
C server receives the msg and puts into buf
if ((numbytes = recv(new_fd, buf, MAXDATASIZE-1, 0)) == -1) {
perror("recv");
exit(1);
}
C server sends the messsage back to the Java client
if ((len = send(new_fd, buf, numbytes, 0)) == -1)
perror("send");
However the Java client cannot receive the msg from the C server, I've tried using DataInputStream, BufferedReader, reading into char[], byte[], converting to string but cannot get the received message. When trying to read into an array on the client side I sometimes get only the first character which leads me to believe it's a blocking problem?
Any help would be appreciated
Code:
C server main loop
while(1) { // main accept() loop
sin_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
perror("accept");
continue;
}
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s);
printf("server: got connection from %s\n", s);
if ((numbytes = recv(new_fd, buf, MAXDATASIZE-1, 0)) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
printf("msg size: '%d' bytes\n",numbytes);
printf("received msg: %s\n",buf);
char* array = (char*)buf;
printf("as char array: %s\n", array);
if (!fork()) { // this is the child process
close(sockfd); // child doesn't need the listener
int len = 0;
if ((len = send(new_fd, buf, numbytes, 0)) == -1)
perror("send");
printf("sent %d bytes\n", len);
close(new_fd);
exit(0);
}
close(new_fd); // parent doesn't need this
}
Java client
public void send(String text){
Socket sock = null;
DataInputStream in = null;
DataOutputStream out = null;
BufferedReader inReader = null;
try {
sock = new Socket(HOST, PORT);
System.out.println("Connected");
in = new DataInputStream(sock.getInputStream());
out = new DataOutputStream(sock.getOutputStream());
out.writeBytes(text + "\n");
String res = "";
//get msg from c server and store into res
System.out.println("Response: " + res);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
sock.close();
//in.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I would like to communicate with 2 applications : a client in C which send a message to the server in TCP and the server in Java which receive it and send an acknowledgement.
Here is the client (the code is a thread) :
static void *tcp_client(void *p_data)
{
if (p_data != NULL)
{
char const *message = p_data;
int sockfd, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
error("ERROR opening socket");
}
server = gethostbyname(ALARM_PC_IP);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(TCP_PORT);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) {
error("ERROR connecting");
}
n = write(sockfd,message,strlen(message));
if (n < 0) {
error("ERROR writing to socket");
}
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0) {
error("ERROR reading from socket");
}
printf("Message from the server : %s\n",buffer);
close(sockfd);
}
return 0;
}
And the java server :
try {
int port = 9015;
ServerSocket server=new ServerSocket(port);
System.out.println("Server binded at "+((server.getInetAddress()).getLocalHost()).getHostAddress()+":"+port);
System.out.println("Run the Client");
while (true) {
Socket socket=server.accept();
BufferedReader in= new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(in.readLine());
PrintStream out=new PrintStream(socket.getOutputStream());
out.print("Welcome by server\n");
out.flush();
out.close();
in.close();
System.out.println("finished");
}
} catch(Exception err) {
System.err.println("* err"+err);
}
With n = read(sockfd,buffer,255); the client is waiting a response and for the server, the message is never ended so it doesn't send a response with PrintStream.
If I remove these lines :
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0) {
error("ERROR reading from socket");
}
printf("Message from the server : %s\n",buffer);
The server knows that the message is finished but the client can't receive the response.
How solve that ?
Thank you
in.readLine() waits for a NL,CR or CR+NL in the stream. Make sure you are sending that in your client message.