TCP的pop網絡模式
1、tcp連接的狀態有以下11種
- CLOSED:關閉狀態
- LISTEN:服務端狀態,等待客戶端發起連接請求
- SYN_SENT:客戶端已發送同步連接請求,等待服務端相應
- SYN_RECEIVED:服務器收到客戶端的SYN請請求,并發送自己的SYN響應,并等待客戶端對這個SYN+ACK的確認(等待客戶端連接確認);
- ESTABLISHED:雙方完成三次握手,連接成功,可以進行數據傳輸;
- FIN_WAIT_1:主動關閉連接的一方(通常是客戶端)已經發送FIN報文,但是還未收到對方的確認。此時仍可以進行數據接收;
- FIN_WAIT_2:主動關閉一方收到了對方的FIN確認,但是沒收到對方的FIN,進入半連接狀態,僅能接收數據;
- CLOSE_WAIT:被動關閉連接的一方已經收到FIN,并發送了確認,但尚關閉連接,等待應用層釋放資源;
- CLOSING:雙方都發送了關閉請求,都在等待對方確認;
- LAST_ACK:被動關閉的一方發送了FIN,等待最后的ACK來關閉連接;
- TIME_WAIT:主動關閉方發送完FIN,并收到對方的FIN+ACK后進入該狀態,等待足夠長的時間確保對方能夠收到確認后再關閉連接;
- 所有連接終止程序完成后,套接字回到CLOSED狀態
tcp所有的狀態轉換圖如下:
2、正常的TCP連接和斷開狀態轉換:
客戶端狀態轉換過程
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
服務端狀態轉換過程
CLOSED->LISTEN->SYN_RCVD->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED
3、其他狀態轉換過程
同時發送斷開連接
ESTABLISHED->FIN_WAIT_1->CLOSING->TIME_WAIT->CLOSED
同時去發送連接(pop網絡模式)
CLOSED->SYN_SENT->SYN_RCVD->ESTABLISHED
Peer-to-Peer,中文譯為“對等網絡”或“點對點技術”,是一種分布式應用架構,其中每個參與者(稱為“節點”)都能夠同時作為客戶端和服務器,直接與其它節點進行數據交互,而不需要通過中央服務器中轉。P2P網絡的關鍵特征是去中心化和資源的分散共享,這使得網絡更加健壯,更能適應大規模的數據交換和共享;
pop網絡模式的代碼實現:
#include <sys/socket.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/poll.h>
#include <arpa/inet.h>int bind_localaddr(const char *ip, short port) {int connfd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in tcpclient_addr;memset(&tcpclient_addr, 0, sizeof(struct sockaddr_in));tcpclient_addr.sin_family = AF_INET;tcpclient_addr.sin_addr.s_addr = htonl(INADDR_ANY);tcpclient_addr.sin_port = htons(port);if (-1 == bind(connfd, (struct sockaddr*)&tcpclient_addr, sizeof(struct sockaddr))) {perror("bind");return -1;}return connfd;
}int connect_tcpserver(int connfd, const char *ip, short port) {struct sockaddr_in tcpserver_addr;memset(&tcpserver_addr, 0, sizeof(struct sockaddr_in));tcpserver_addr.sin_family = AF_INET;tcpserver_addr.sin_addr.s_addr = inet_addr(ip);tcpserver_addr.sin_port = htons(port);int ret = connect(connfd, (struct sockaddr*)&tcpserver_addr, sizeof(struct sockaddr_in));if (ret) {return -1;}return connfd;
}void *client_thread(void *arg) { int clientfd = *(int *)arg;while (1) { printf(" client > ");char buffer[128] = {0};scanf("%s", buffer);if (strcmp(buffer, "quit") == 0) {break;}int len = strlen(buffer);printf("count: %d, send: %s\n", len, buffer);send(clientfd, buffer, len, 0);}
}int main(int argc, char *argv[]) {if (argc < 3) {printf("arg\n");return -1;}char *ip = argv[1];int port = atoi(argv[2]);int sockfd = bind_localaddr("0.0.0.0", 8000);while (1) {int ret = connect_tcpserver(sockfd, ip, port);if (ret < 0) {usleep(1);continue;}break;}printf("connect success\n");pthread_t thid; pthread_create(&thid, NULL, client_thread, &sockfd);struct pollfd fds[1] = {0};fds[0].fd = sockfd; fds[0].events = POLLIN;while (1) {int nready = poll(fds, 1, -1);if (fds[0].revents & POLLIN) {char buffer[128] = {0}; int count = recv(sockfd, buffer, 128, 0);if (count == 0) {fds[0].fd = -1; fds[0].events = 0;close(sockfd);break;}printf("recv --> count: %d, buffer: %s\n", count, buffer);}}
}