因此,我有一個簡單的小型服務器從我的主程序的單獨線程開始(此線程的代碼位於底部),一切都很好,我可以用telnet連接到它併發送消息和什麼。如果我發送「quit」,程序完全按照預期執行,它會退出,但如果我發送任何其他消息,則會收到套接字已關閉的日誌,但從telnet連接仍然保持活動狀態 - 我知道這一點因爲我知道,因爲telnet仍然像其連接一樣。爲什麼telnet的連接不被切斷?它如何在「ESTABLISHED」狀態下保持活躍狀態?關閉套接字後,套接字連接保持ESTABLISHED
lsof的:
bash 24122 Dan cwd DIR 1,2 340 3782037 /Users/Dan/Dropbox/PersonalDev/cruentus
bash 24813 Dan cwd DIR 1,2 340 3782037 /Users/Dan/Dropbox/PersonalDev/cruentus
bash 25782 Dan cwd DIR 1,2 340 3782037 /Users/Dan/Dropbox/PersonalDev/cruentus
bash 26395 Dan cwd DIR 1,2 340 3782037 /Users/Dan/Dropbox/PersonalDev/cruentus
vim 26462 Dan cwd DIR 1,2 340 3782037 /Users/Dan/Dropbox/PersonalDev/cruentus
vim 26462 Dan 4u REG 1,2 16384 16889838 /Users/Dan/Dropbox/PersonalDev/cruentus/.cruentus.c.swp
cruentus 26474 Dan cwd DIR 1,2 340 3782037 /Users/Dan/Dropbox/PersonalDev/cruentus
cruentus 26474 Dan txt REG 1,2 14840 16889520 /Users/Dan/Dropbox/PersonalDev/cruentus/obj/cruentus
cruentus 26474 Dan txt REG 1,2 600576 748159 /usr/lib/dyld
cruentus 26474 Dan txt REG 1,2 303132672 15641156 /private/var/db/dyld/dyld_shared_cache_x86_64
cruentus 26474 Dan 0u CHR 16,0 0t532754 899 /dev/ttys000
cruentus 26474 Dan 1u CHR 16,0 0t532754 899 /dev/ttys000
cruentus 26474 Dan 2u CHR 16,0 0t532754 899 /dev/ttys000
cruentus 26474 Dan 3u IPv4 0x5e17dc80b705100f 0t0 TCP *:terabase (LISTEN)
cruentus 26474 Dan 5u IPv4 0x5e17dc80a55f88d7 0t0 TCP localhost:krb524->localhost:55775 (ESTABLISHED)
telnet 26482 Dan cwd DIR 1,2 340 3782037 /Users/Dan/Dropbox/PersonalDev/cruentus
lsof 26483 Dan cwd DIR 1,2 340 3782037 /Users/Dan/Dropbox/PersonalDev/cruentus
grep 26484 Dan cwd DIR 1,2 340 3782037 /Users/Dan/Dropbox/PersonalDev/cruentus
服務器代碼:
void *controller_thread(void *a __unused) {
puts("Starting controller thread");
int contsock, asock, alen;
struct sockaddr_in saddr, inaddr;
struct timeval tv;
struct linger lingading;
if ((contsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("controller : socket");
return NULL;
}
bzero((void*)&saddr, sizeof(struct sockaddr_in));
saddr.sin_len = sizeof(struct sockaddr_in);
saddr.sin_family = AF_INET;
saddr.sin_port = htons(4444);
saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
if (bind(contsock, (const struct sockaddr*)&saddr, (socklen_t)saddr.sin_len) != 0) {
perror("controller : bind");
return NULL;
}
if (listen(contsock, 1) != 0) {
perror("controller : listen");
}
lingading.l_onoff = 1;
lingading.l_linger = 5;
if (setsockopt(contsock, SOL_SOCKET, SO_LINGER_SEC, (const void*)&lingading, (socklen_t)sizeof(struct linger)) != 0) {
perror("controller : setsockopt1");
return NULL;
}
tv.tv_sec = 5;
tv.tv_usec = 0;
if (setsockopt(contsock, SOL_SOCKET, SO_SNDTIMEO, (const void*)&tv, (socklen_t)sizeof(struct timeval)) != 0) {
perror("controller : setsockopt2");
return NULL;
}
tv.tv_sec = 5;
tv.tv_usec = 0;
if (setsockopt(contsock, SOL_SOCKET, SO_RCVTIMEO ,(const void*)&tv, (socklen_t)sizeof(struct timeval)) != 0) {
perror("controller : setsockopt3");
return NULL;
}
bzero((void*)&inaddr, sizeof(struct sockaddr_in));
alen = sizeof(struct sockaddr_in);
if ((asock = accept(contsock, (struct sockaddr *)&inaddr, (socklen_t*)&alen)) != -1) {
printf("Got controller connection: %s:%d\n", inet_ntoa(inaddr.sin_addr), ntohs(inaddr.sin_port));
tv.tv_sec = 5;
tv.tv_usec = 0;
if (setsockopt(asock, SOL_SOCKET, SO_RCVTIMEO ,(const void*)&tv, (socklen_t)sizeof(struct timeval)) != 0) {
perror("controller : setsockopt3");
return NULL;
}
char abuf[4];
if (read(asock, abuf, 4) == 4 && strncmp("quit", abuf, 4) == 0) {
puts("Quitting now!");
exit(0);
}
} else {
perror("controller : accept");
}
puts("Failed to quit from controller");
if (shutdown(contsock, SHUT_WR) != 0) {
if (errno != ENOTCONN)
perror("controller : shutdown");
}
char tmp;
while (read(contsock, &tmp, 1) == 1) {
// remove all packets...
}
puts("Shutdown controller socket");
if (close(contsock) != 0) {
perror("controller : close");
}
puts("Closed controller socket");
return NULL;
}
謝謝!起初沒有看到! – DanZimm