簡體   English   中英

Java 客戶端只接收來自 C 服務器的第一個響應

[英]Java client only receives first response from C server

我正在創建一個由 Java 客戶端和 C 服務器組成的簡單游戲。 當客戶端向服務器發送第一個請求時,就可以了。 服務器發送響應,客戶端讀取它。 但是當客戶端發送第二個請求時,服務器像往常一樣發送響應,但客戶端什么也沒讀。 當我從響應中刪除 \\n 時,clinet 卡在 readLine() 上,這沒問題,但是當我放回 \\n 時, readLine() 什么也沒讀。 我非常絕望,我嘗試了各種操作,並更改了來自服務器的消息 1000 次,但沒有任何效果。

下面是連接方法:

public int connect() {
    try {
        if (port != 0 && !host.equals(null)) {
            socket = new Socket(host, port);
            socket.setSoTimeout(5000);
            socket.setKeepAlive(true);
        } else {
            socket = new Socket("localhost", 50001);
        }

        out = new OutputStreamWriter(socket.getOutputStream());
        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

    } catch (UnknownHostException ex1) {
        System.out.println("Unknown host: " + host);
        return 1;
    } catch (IOException ex2) {
        System.out.println("No I/O: " + ex2.getMessage());
        return 2;
    }
    return 0;
}

以下是溝通的方法:

public String listRooms() throws DisconnectedException, IOException {
    this.send(LIST_ROOMS);

    String data = this.receive();
    System.out.println("Action: " + LIST_ROOMS + " Result: " + data);

    return data;        
}

public int createRoom(String playerName) throws IOException, DisconnectedException {
    this.send(playerName, CREATE_ROOM);

    int result = this.receiveInt();
    System.out.println("Action: " + CREATE_ROOM + " Result: " + result);
    return result;
}

public void joinRoom(String playerName, int number) throws IOException, DisconnectedException {

    String message = number + "\0" + playerName;

    this.send(message, JOIN_ROOM);

    try {
        System.out.println("Action: " + JOIN_ROOM + " Result: " + this.receive());
    } catch (SocketTimeoutException e) {
        throw new DisconnectedException("Connection with server lost...");
    }
}

private void send(String message, int actionNumber) throws IOException {
    out.write((char) actionNumber);
    out.write(message);
    out.flush();
}

private void send(int actionNumber) throws IOException {
    out.write((char) actionNumber);
    out.flush();
}

private int receiveInt() throws IOException {
    int response = in.read();
    System.out.println(response);


    return 0;
}

private String receive() throws IOException {
    String answer = in.readLine();

    System.out.println("ANSWER: " + answer);        

    if (answer == null) {
        System.out.println("You recieved nothing Jon Snow...");
    } else if ("0".equals(answer)) {
        System.out.println("Error recieveing answer from server");
        return "0";
    }

    return answer;
}

這是服務器:

#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>

#include "room.h"

void error_message(const char *msg);

typedef struct thread_args
{
    int client_sock;
    char ip_address[16];
} thread_args;


void *thread_service(void *args)
{
    int client_sock;
    char buffer[256] = "";
    char cbuf;
    int n;
    char address[16] = "";
    int result = 0;
    room *room = NULL;


    client_sock = ((thread_args *) args)->client_sock;
    strcpy(address, ((thread_args *) args)->ip_address);

    pthread_detach(pthread_self());

    while(1)
    {
        if ((recv(client_sock, &cbuf, 1, 0)) == -1)
        {
            printf("Receive message from %s failure\n", address);
            break;
        }

        switch (cbuf) {
            case 0:
                result = create_room(&room, client_sock);

                if(!result)
                {
                    /* TODO */
                }
                memset(buffer, 0, 256);
                sprintf(buffer, "%d\n", result);

                n = send(client_sock, buffer, 256, 0);

                if (n <= 0) {
                  perror("ERROR writing to socket\n");
                  close(client_sock);
                  break;
                }
                printf("sent\n");
                break;
            case 1:
                result = join_room(&room, client_sock);
                if(!result)
                {
                    /* TODO */
                }

                printf("Join to room for %s\n", address);
                sprintf(buffer, "%d\n", result);
                n = send(client_sock, buffer, 256, 0);

                if (n <= 0) {
                  perror("ERROR writing to socket\n");
                  break;
                }

                break;
            case 2:
                printf("List rooms\n");
                memset(buffer, 0, 256);
                result = list_rooms(buffer);

                if(!result) {
                    /* TODO */
                }

                printf("Sending message: %s", buffer);
                n = send(client_sock, buffer, 256, 0);

                if (n <= 0) {
                  perror("ERROR writing to socket\n");
                  close(client_sock);
                  break;
                }
                printf("Sent\n");
                break;
            case 5:
                exit(0);
                break;
        }

    }
    close(client_sock);
    free(args);
    return 0;
}

int main(int argc, char *argv[])
{
int sock_fd = 0, new_sock_fd = 0, port = 0, clilen = 0;
struct sockaddr_in serv_addr, cli_addr;
int *th_socket;
pthread_t thread_id;
thread_args *args = (thread_args *)malloc(sizeof(thread_args));
char address[16];
int yes = 1;

if(argc < 2)
{
    fprintf(stderr, "Error missing port");
    return 0;
}

sock_fd = socket(AF_INET, SOCK_STREAM, 0);

if(sock_fd < 0)
    fprintf(stderr, "Error opening socket");

memset(&serv_addr, 0, sizeof(serv_addr));

port = atoi(argv[1]);

serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
serv_addr.sin_addr.s_addr = INADDR_ANY;

if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == 0)
{
    printf("Socket options was set.\n"); //TODO
}
else
{
    printf("Set socket options failure.\n"); //TODO
}

if(bind(sock_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
    error_message("Error in connection");

listen(sock_fd, 5);

if (pthread_mutex_init(&lock, NULL) != 0)
{
    printf("Mutex init failed.\n");
    return 1;
}

while(1)
{
    printf("Waiting for new connection\n");
    clilen = sizeof(cli_addr);
    new_sock_fd = accept(sock_fd, (struct sockaddr *)&cli_addr, &clilen);

    if (new_sock_fd < 0) {
        printf("Error accepting new connection!\n");
        continue;
    }

    strcpy(args->ip_address, inet_ntoa(cli_addr.sin_addr));
    args->client_sock = new_sock_fd;

    if (new_sock_fd > 0 ) {
        th_socket=malloc(sizeof(int));
        *th_socket=new_sock_fd;

        printf("Creating new thread for %s\n", args->ip_address);
        pthread_create(&thread_id, NULL, (void *)&thread_service, (void *)args);
    } else {
        printf("Error creating thread for new connection.\n");
        return -1;
    }
}

return 0;
}

所以如果你想發送 C servera 消息,它看起來像這樣:

String message = "Hello world!";

OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream());
out.write(message + "\n");
out.flush();

更新:A 已經發現,這是一個非常討厭的錯誤,也許它會幫助其他人.. 在從 JAVA 客戶端到服務器的消息中必須(在我的情況下)手動附加“\\n”字符,否則它會發送一些字符混淆服務器。 所以我的代碼看起來像這樣out.write(message + "\\n"); 然后調用flush()就可以了。

您必須添加 enline 字符,但是如果您使用了 printWriter,那么您可以使用println方法...

PrintWriter pw =  new PrintWriter(socket.getOutputStream(), true);
pw.println("Bla bla");

所以答案很簡單。 如果您使用的是 OutputStreamWritter,則必須在消息中添加換行符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM