2

I would like to apologise for my english. It's not my native language.

I'm trying to write simple TCP server and client. I have a problem with sending a number from client to server. Here is the code from client side:

public class ConnectionHandler {
  private InetAddress address;
  private int port;

  private Socket socket;
  private DataOutputStream dos;
  private DataInputStream dis;

  public ConnectionHandler(String ipAddress, String port) {
    try {
      address = InetAddress.getByName(ipAddress);
      this.port = Integer.parseInt(port);
      connectionHandle();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  private void connectionHandle() {
    try {
      socket = new Socket(address, port);
      dos = new DataOutputStream(socket.getOutputStream());
      dis = new DataInputStream(socket.getInputStream());

      getCatalogueList();
    } catch (Exception e) {
      e.printStackTrace();
  } 
  private void getCatalogueList() {
    try {
      dos.writeInt(1);
      sendFile();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  public void sendFile() {
    try{
      dos.writeInt(2);
    } catch(Exception e) {
      e.printStackTrace();
    }
  }

Everything works fine when I'm sending number 1 in getCatalogueList(), but then in sendFile I'm trying to send number 2, but my server is getting 0. I've checked that if I'm sending numbers in one function:

private void getCatalogueList() {
  dos.writeInt(1);
  dos.writeInt(2);
}

everything works. Problem is only when I'm using two different functions.

If someone could help me how to prevent that and explain to me why this is happening I will be really grateful.


Server code (it's in C, I'm using bsd sockets)

int handleConnection(int clientSocket) {
  short connectionClosed = False;
  long action;

  while(!connectionClosed) {
    recv(clientSocket, &action, sizeof(int), 0);
    action = ntohl(action);
    printf("%i\n", action);
  }
  return 0;
}

int main() {
  const int port = 8080;
  const int maxConnection = 20;

  int listeningSocket, clientSocket;

  struct sockaddr_in server, client;
  struct hostent *host;
  socklen_t sin_size = sizeof(struct sockaddr_in);

  char myhostname[1024];

  listeningSocket = socket(PF_INET, SOCK_STREAM, 0);
  gethostname(myhostname, 1023);
  host = gethostbyname(myhostname);

  server.sin_family = AF_INET;
  server.sin_port = htons(port);
  server.sin_addr = *(struct in_addr*) host->h_addr;

  if (bind(listeningSocket, (struct sockaddr*) &server, sizeof(struct sockaddr)) == -1) {
    return -1;
  }

  listen(listeningSocket, maxConnection);
  while(True) {
    sin_size = sizeof(struct sockaddr_in);
    clientSocket = accept(listeningSocket, (struct sockaddr*) &client, &sin_size);
    if(fork() == 0) {
      handleConnection(clientSocket);
      close(clientSocket);
      exit(0);
    }
    else {
      printf("Waiting for connection.\n");
      continue;
    }
  }
  return 0;
}
Ironus
  • 21
  • 3
  • 1
    (1) show your server code as well, (2) is this your *exact* code, or have you created an excerpt from a larger program, and (3) do you subclass `ConnectionHandler`? – kdgregory May 23 '15 at 13:05
  • I've added server code. It's part of a bigger program (client has GUI in swing), but that's all of the parts responsible for connection between server and client. I have only removed some lines responsible for sending (on server) and receiving (on client) file tree. I don't think they have any meaning here, because I'm using DataInputStream, not Output to do that. I can paste them if it will help. My ConnectionHandler doesn't extend any superior class if that is what you mean by subclass (I'm not sure if I understood u correctly). – Ironus May 23 '15 at 13:21

1 Answers1

0

You're ignoring the count returned by recv(). It could be -1, indicating an error page, or zero, indicating end of stream, or any positive value between 1 and sizeof int inclusive. Instead you're assuming it filled the buffer.

It has nothing to do with DataOutputStream.

You're also leaking client sockets in the parent process, and not checking for errors from socket() or accept() or listen().

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Changing recv to if(recv(clientSocket, &action, sizeof(int), 0) != -1) didn't have any effect. I'm still getting 0 when trying to get 2 – Ironus May 23 '15 at 13:48
  • That's not a test for three different possibilities. There is no correct way to do that without storing the result into a variable. – user207421 May 23 '15 at 13:54
  • I'm not exactly sure what I should do. I mean, I'm sending int from client and receiving int on server. Now if I understood you correctly, I should do another recv to another variable and then it should be ok? – Ironus May 23 '15 at 14:02
  • Sigh. Read what I wrote again. There are three possible results, and you need to test for all of them, including receiving some but not all of the data. – user207421 May 23 '15 at 14:17
  • Ok, I can do it like that `int msg = recv(clientSocket, &action, sizeof(int), 0);` then I can make if-else statement for checking msg value. What conditions should I put in? `msg == -1`, `msg == 0` and `msg > 0 && msg <= sizeof(int)`? And what next? Ok, -1 is error and 0 is end of stream (so I assume I should while loop until 0 is reached?) and what in third scenario? I wander in the dark. If you could tell me step by step what to do. – Ironus May 23 '15 at 14:40