编辑:首先,我知道什么是 TCP 和 UDP,以及它们之间的区别,但是如何解释我能够在客户端上从服务器接收,但不能发送,如下所示...?
我用 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
最佳答案
TCP 是面向连接的。一旦建立了 TCP 连接,您就会得到所谓的套接字对。 Socket 对是源 ip 地址和源端口以及目标 ip 地址和目标端口的组合。连接由这 4 个参数唯一标识。
在整个 session 期间,将使用相同的 ip 地址和端口。
因此,如果一个网络接口(interface)不再可用,您就会遇到问题,因为每个网络接口(interface)都会有一个 IP 地址,如果它不再可用,则 TCP 连接将无法再选择其他网络接口(interface)。
TCP 不支持更改连接两端的 IP 地址。
需要相当长的时间才能检测到有问题。你认为你仍然可以发送,但是,TCP 会重传几次,最终你会看到发送失败。这甚至需要几分钟。根据您的套接字是否阻塞,您会注意到发送将在 IP@ 已更改的错误情况下阻塞。从 TCP 的角度来看,这就像断线。
关于java - 在客户端更改网络 IP 后,可以从 Android(客户端)在 C(服务器)中发送但不能接收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29134010/