在客户端上更改网络IP后,可以从Android(客户端)发送但不能在C(服务器)中接收

时间:2015-03-18 22:36:51

标签: java android c sockets tcp

编辑:在其他任何事情之前,我知道TCP和UDP是什么,以及差异,但是如何解释我能够从客户端从服务器接收,但不能发送,如下所示......?< / p>

我在C中创建了一个服务器应用程序,在Java中创建了一个客户端应用程序,我将其部署到Android。 我有一个奇怪的问题,我无法克服。

当我的手机IP发生变化时(例如,当切换到移动网络时,从Wifi,或反之亦然),C中的应用程序不再能够接收数据,只是为了发送,即使手机发送它,也没有任何错误

重新连接到同一网络时不会发生这种情况。

我尝试了很多东西,并以C:

结束了这一点
void *receive_thread(){
    pthread_detach(pthread_self());

    struct sockaddr_in dest; /* socket info about the machine connecting to us */
    struct sockaddr_in serv; /* socket info about our server */
    int mysocket;            /* socket used to listen for incoming connections */
    socklen_t socksize = sizeof(struct sockaddr_in);

    memset(&serv, 0, sizeof(serv));           /* zero the struct before filling the fields */
    serv.sin_family = AF_INET;                /* set the type of connection to TCP/IP */
    serv.sin_addr.s_addr = htonl(INADDR_ANY); /* set our address to any interface */
    serv.sin_port = htons(PORTNUMRCV);           /* set the server port number */    

    mysocket = socket(AF_INET, SOCK_STREAM, 0);

    //fcntl(mysocket, F_SETFD, O_NONBLOCK);

    /* bind serv information to mysocket */
    bind(mysocket, (struct sockaddr *)&serv, sizeof(struct sockaddr));

    /* start listening, allowing a queue of up to 1 pending connection */
    listen(mysocket, 1);

    int consocket = accept(mysocket, (struct sockaddr *)&dest, &socksize);
    while(consocket){
        //socklen_t fromlen;
        //fromlen = sizeof inet_ntoa(dest.sin_addr);
        char receivemsg[128];

        int rlen = recv(consocket, &receivemsg, 128, 0); //receive data
        int err = errno;
        //printf("recv error: %d\n", err);
        printf("Received string: %s from %s \n", receivemsg, inet_ntoa(dest.sin_addr));
        if(rlen > 0){
            receivemsg[rlen] = '\0';
            if(comparestr(KEY, receivemsg) == 1){
                printf("Local client\n");
                incrementor++;
            } else if(comparestr(KEY, receivemsg) == 2){
                printf("Remote client\n");
                incrementor--;
            } else {
                printf("Wrong key!\n");
            }
        } else {
            printf("Care!!!! Receiving: %d \n", rlen);
        }
        close(consocket);
        consocket = accept(mysocket, (struct sockaddr *)&dest, &socksize);
    }
    printf("Receive thread ended!\n");
    receive_thread_up = 0;
}

void *send_thread(){
    pthread_detach(pthread_self());

    struct sockaddr_in dest; /* socket info about the machine connecting to us */
    struct sockaddr_in serv; /* socket info about our server */
    int mysocket;            /* socket used to listen for incoming connections */
    socklen_t socksize = sizeof(struct sockaddr_in);

    memset(&serv, 0, sizeof(serv));           /* zero the struct before filling the fields */
    serv.sin_family = AF_INET;                /* set the type of connection to TCP/IP */
    serv.sin_addr.s_addr = htonl(INADDR_ANY); /* set our address to any interface */
    serv.sin_port = htons(PORTNUMSND);           /* set the server port number */

    mysocket = socket(AF_INET, SOCK_STREAM, 0);

    /* bind serv information to mysocket */
    bind(mysocket, (struct sockaddr *)&serv, sizeof(struct sockaddr));

    /* start listening, allowing a queue of up to 1 pending connection */
    listen(mysocket, 1);

    int consocket = accept(mysocket, (struct sockaddr *)&dest, &socksize);
    while(consocket){
        //printf("Incoming connection from %s - sending string\n", inet_ntoa(dest.sin_addr));
        int slen = send(consocket, KEY, 3*sizeof(KEY), 0); //send data
        if(slen>0)printf("Sent string: %s to %s \n", KEY, inet_ntoa(dest.sin_addr));
        else {
            printf("Care!!! Sending: %d \n", slen);
        }       
        close(consocket);
        consocket = accept(mysocket, (struct sockaddr *)&dest, &socksize);
    }
    printf("Send thread ended!\n");
    send_thread_up = 0;
}

这就是Java:

public static int sendString(String str) throws IOException{
    System.out.println("Sending string: " + str);
    out.println(str);
    return 0;
}

public static String receiveString(){
    String s = " ";
    try {
        s = in.readLine();
    } catch (SocketException e) {
        System.out.println("Socket Exception: " + e);
    } catch (IOException e) {
        System.out.println("IOException on receive: " + e);
    }
    System.out.println("Received string: " + s);
    return s;
}
public static String reverseString(String str){
    String newStr = " ";
    newStr = new StringBuilder(str).reverse().toString();
    return newStr;
}

我的猜测是recv卡住,因此我尝试添加

fcntl(mysocket, F_SETFD, O_NONBLOCK);

,在不工作之后,我评论了它。 也许使用UDP套接字?我可能会遇到诸如消息未到达或未完整等问题。 我们也欢迎改进我的代码的建议!

这是C:

中的输出
Thread: No connection, waiting...
Sent string: I4mP4ssw0rd7 to 192.168.1.2
Received string: I4mP4ssw0rd7
 from 192.168.1.2
Local client
Sent string: I4mP4ssw0rd7 to 192.168.1.2
Thread: Local connection!
Received string: I4mP4ssw0rd7
 from 192.168.1.2
Local client
Sent string: I4mP4ssw0rd7 to 192.168.1.2
Sent string: I4mP4ssw0rd7 to 87.edited
Sent string: I4mP4ssw0rd7 to 87.edited
Sent string: I4mP4ssw0rd7 to 87.edited
Sent string: I4mP4ssw0rd7 to 87.edited
Sent string: I4mP4ssw0rd7 to 87.edited

以下是Java的输出:

03-18 22:52:45.831  13899-13899/willymatica.alarmapp1 I/System.out﹕ Connected!
03-18 22:52:49.375  13899-13920/willymatica.alarmapp1 I/System.out﹕ Connected locally!
03-18 22:52:49.585  13899-13920/willymatica.alarmapp1 I/System.out﹕ Received string: I4mP4ssw0rd7
03-18 22:52:54.900  13899-13920/willymatica.alarmapp1 I/System.out﹕ Sending string: I4mP4ssw0rd7
03-18 22:52:54.910  13899-13920/willymatica.alarmapp1 I/System.out﹕ Connected locally!
03-18 22:52:54.970  13899-13920/willymatica.alarmapp1 I/System.out﹕ Received string: I4mP4ssw0rd7
03-18 22:53:00.265  13899-13920/willymatica.alarmapp1 I/System.out﹕ Sending string: I4mP4ssw0rd7
03-18 22:53:00.285  13899-13920/willymatica.alarmapp1 I/System.out﹕ Connected locally!
03-18 22:53:00.315  13899-13920/willymatica.alarmapp1 I/System.out﹕ Received string: I4mP4ssw0rd7
03-18 22:53:05.631  13899-13920/willymatica.alarmapp1 I/System.out﹕ Sending string: I4mP4ssw0rd7
03-18 22:53:05.631  13899-13920/willymatica.alarmapp1 I/System.out﹕ Connected remotely!
03-18 22:53:05.851  13899-13920/willymatica.alarmapp1 I/System.out﹕ Received string: I4mP4ssw0rd7
03-18 22:53:11.266  13899-13920/willymatica.alarmapp1 I/System.out﹕ Sending string: 7dr0wss4Pm4I
03-18 22:53:11.286  13899-13920/willymatica.alarmapp1 I/System.out﹕ Connected remotely!
03-18 22:53:11.516  13899-13920/willymatica.alarmapp1 I/System.out﹕ Received string: I4mP4ssw0rd7
03-18 22:53:16.912  13899-13920/willymatica.alarmapp1 I/System.out﹕ Sending string: 7dr0wss4Pm4I
03-18 22:53:16.932  13899-13920/willymatica.alarmapp1 I/System.out﹕ Connected remotely!
03-18 22:53:17.162  13899-13920/willymatica.alarmapp1 I/System.out﹕ Received string: I4mP4ssw0rd7
03-18 22:53:22.547  13899-13920/willymatica.alarmapp1 I/System.out﹕ Sending string: 7dr0wss4Pm4I
03-18 22:53:22.567  13899-13920/willymatica.alarmapp1 I/System.out﹕ Connected remotely!
03-18 22:53:23.198  13899-13920/willymatica.alarmapp1 I/System.out﹕ Received string: I4mP4ssw0rd7
03-18 22:53:28.933  13899-13920/willymatica.alarmapp1 I/System.out﹕ Sending string: 7dr0wss4Pm4I
03-18 22:53:28.933  13899-13920/willymatica.alarmapp1 I/System.out﹕ Connected remotely!
03-18 22:53:29.113  13899-13920/willymatica.alarmapp1 I/System.out﹕ Received string: I4mP4ssw0rd7

1 个答案:

答案 0 :(得分:0)

TCP是面向连接的。建立TCP连接后,您将获得所谓的套接字对。套接字对是源IP地址和源端口以及目标IP地址和目标端口的组合。连接由这4个参数唯一标识。

在整个会话期间,将使用相同的IP地址和端口。

因此,如果一个网络接口不再可用,则会出现问题,因为每个网络接口都有一个IP地址,如果不再可用,则TCP连接不能再选择其他网络接口。

TCP不支持在连接的任何一端更改IP地址。

检测到存在问题需要相当长的时间。您认为您仍然可以发送,但是,TCP将重新传输几次,最终您将看到发送失败。这需要几分钟。根据您的套接字是否阻塞,您会注意到发送将阻止IP @已更改的错误情况。从TCP的角度来看,这就像断线。