android - Android Socket 每 20 秒卡住一次
问题描述
我在动作游戏中使用 TCP 套接字连接,我们使用锁步同步,客户端每秒将接收 20 - 40 个数据包。游戏在PC上运行正常,但在Android设备上运行时,套接字每20秒就会卡住一次
我尝试使用 Unity3D 的 C# 套接字、Android Java 套接字和 Android 原生 C 套接字和阻塞/非阻塞模式,每个数据包的小/大(1 字节/100 字节)数据,每秒更少/更多(5/50)个数据包,使用单线程/主线程,在多个 Android 设备上,它们都有相同的问题。
PS:似乎 20 秒的持续时间是基于设备,而不是我的应用程序或连接;这意味着如果最后一次卡住发生在 1:00:00,下一次卡住将发生在 1:00:20,即使我们重新连接或重新启动应用程序也是如此。
Android原生C代码:
extern "C" JNIEXPORT int JNICALL
Java_com_example_ymoon_sockettest_MainActivity_connect(JNIEnv *env, jobject /* this */)
{
__android_log_print(ANDROID_LOG_INFO, "CSocket", "Connecting...");
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) return -1;
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(12350);
server.sin_addr.s_addr = inet_addr("192.168.3.66");
if (connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0)
{
close(sock);
return -2;
}
__android_log_print(ANDROID_LOG_INFO, "CSocket", "Connected");
char buf[100];
int t = -1;
int received = 0;
while (true)
{
int count = recv(sock, &buf, 100, 0);
if (count < 1) break;
received += count;
struct timeval tv;
gettimeofday(&tv, NULL);
int m = tv.tv_sec * 1000 + tv.tv_usec / 1000;
int diff = m - t;
t = m;
std::string p = t < 0 ? "" : diff < 50 ? "-" : diff < 100 ? "-|" : diff < 150 ? "--|" :
diff < 250 ? "---|" : diff < 500 ? "----|" : diff < 1000 ? "-----|" : "------|";
__android_log_print(diff > 500 ? ANDROID_LOG_ERROR : ANDROID_LOG_INFO,
"CSocket", "%i | %s %i", received, p.c_str(), diff);
}
close(sock);
return 0;
}
难道我做错了什么 ?这是我第一次在stackoverflow上提出问题,对不起我的英语不好,任何帮助或建议都非常感谢,谢谢。
编辑:添加服务器代码,我重写了一个简单的 tcp 服务器来测试(Window 平台)
int main()
{
addrinfo conf, *add = nullptr;
memset(&conf, 0, sizeof(conf));
conf.ai_flags = AI_PASSIVE;
conf.ai_socktype = SOCK_STREAM;
conf.ai_family = AF_INET;
if (getaddrinfo(nullptr, "12350", &conf, &add)) return 0;
SOCKET serverSock = socket(AF_INET, SOCK_STREAM, 0);
char opt = 1;
if (setsockopt(serverSock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
setsockopt(serverSock, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) == -1 ||
bind(serverSock, add->ai_addr, add->ai_addrlen) == -1 ||
listen(serverSock, 0) == -1)
{
close(serverSock);
return 0;
}
printf("Listening....\n");
sockaddr_storage incoming_addr;
int size = sizeof(incoming_addr);
SOCKET clientSock = accept(serverSock, (sockaddr*)&incoming_addr, &size);
printf("Client connected\n");
char buf[1] = { 0 };
int sendCount = 0;
while (true)
{
time_t t = time(nullptr);
tm *lt = localtime(&t);
printf("%02d:%02d:%02d Send to client %i\n", lt->tm_hour, lt->tm_min, lt->tm_sec, ++sendCount);
if (send(clientSock, buf, 1, 0) < 1) break;
Sleep(200);
}
close(serverSock);
return 0;
}
编辑:添加 WireShark 捕获图像: 发生卡住时 Wireshark 拍摄
解决方案
我已经在我家和另一个 WIFI 环境中对其进行了测试(代码发布在这里),它运行良好。唯一的区别是WIFI环境,所以我认为可能是我们公司的WIFI网络设置导致了这个问题。
推荐阅读
- django - Django Rest 框架:按字段获取数据
- c++ - 将父母作为孩子传递给函数c ++
- javascript - 如何解析菜单链接
- xslt - 满足条件时分组数据
- google-cloud-platform - 如何在 Google Dataproc 上安排 Spark 作业?
- vue.js - 带有链接的 VueJs Vuetify 自动完成
- php - 尝试根据运输类别在 Woocommerce 中的产品缩略图中添加“免费送货”徽章
- auth0 - 使用 Auth0 登录成功,但仍然返回 401“拒绝访问”?
- java - 如何通过 retrofit2 发送 ArrayList 和 Multipart?(错误:预期的 begin_object 但是字符串)
- android - 我可以在扩展 Android 中的 AppCompactDialogFragment 的类中调用另一个类构造函数吗?