Cet article présente principalement les informations pertinentes sur la communication par socket Linux pour obtenir le numéro de port source local. Les amis dans le besoin peuvent s'y référer
Il existe de nombreuses informations sur la communication réseau TCP IP. Mode paquets de données IP pour une communication de bout en bout. Un paquet de données TCP typique est le suivant
Vous pouvez voir que le paquet de données contient le numéro de port source et le numéro de port de destination lorsque le socket client initie une connexion au. serveur, le système donnera au socket un numéro de port source attribué au hasard, et nous pourrons obtenir les informations de port d'origine du socket connecté avec succès via getsocketname.
Prototype de fonction
#include <sys/socket.h> int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
Paramètres :
Poignée de connexion socket sockfd
pointeur d'adresse réseau addr, utilisé pour stocker les informations d'adresse de socket locale,
taille de l'espace addrlen addr
Résultat renvoyé, si l'appel réussit, renvoie 0 et stocke les informations d'adresse réseau locale dans Dans addr, -1 est renvoyé en cas d'échec et les informations d'erreur sont reflétées via errno.
source_port.cpp
#include <cstring> #include <cstdio> #include <cstdlib> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netdb.h> #include <errno.h> #include <unistd.h> #include <arpa/inet.h> void safe_close(int &sock); int main(int argc, char *argv[]) { int sockfd = 0, n = 0; socklen_t len = 0; char host[512] = {0}; char buf[1024] = {0}; struct hostent *server; struct sockaddr_in serv_addr, loc_addr; if (argc < 2) { printf("Please input host name\n"); exit(-1); } strncpy(host, argv[1], sizeof(host)); server = gethostbyname(host);// 判断输入的域名是否正确 if (NULL == server) { printf("find host: %s failed.\n", host); exit(-1); } if (-1 == (sockfd = socket(AF_INET, SOCK_STREAM, 0))) {// 创建socket memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf), "new socket failed. errno: %d, error: %s", errno, strerror(errno)); perror(buf); exit(-1); } memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(80);// http标准端口号 memcpy(&serv_addr.sin_addr.s_addr, server->h_addr, server->h_length); if (-1 == inet_pton(AF_INET, host, &serv_addr.sin_addr)) { memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf), "inet_pton failed. errno: %d, error: %s", errno, strerror(errno)); perror(buf); exit(-1); } if (-1 == connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) {// 连接socket memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf), "connect socket failed. errno: %d, error: %s", errno, strerror(errno)); perror(buf); exit(-1); } printf("connect to %s success.\n", host); len = sizeof(sizeof(loc_addr)); memset(&loc_addr, 0, len); if (-1 == getsockname(sockfd, (struct sockaddr *)&loc_addr, &len)) {// 获取socket绑定的本地address信息 memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf), "get socket name failed. errno: %d, error: %s", errno, strerror(errno)); perror(buf); safe_close(sockfd); exit(-1); } if (loc_addr.sin_family == AF_INET) {// 打印信息 printf("local port: %u\n", ntohs(loc_addr.sin_port)); } safe_close(sockfd); return 0; } void safe_close(int &sock) { if (-1 != sock) { shutdown(sock, SHUT_RDWR); sock = -1; } }
Ce programme va d'abord démarrer un socket pour se connecter à un serveur http ordinaire (baidu, qq, 163, csdn) , Lorsque le socket est connecté, l'adresse locale liée à la connexion est obtenue via getsocketname et le numéro de port source est obtenu via cette adresse.
Terminal 1 : Compiler et exécuter
$ g++ source_port.cpp $ ./a.out www.baidu.com connect to www.baidu.com success. local port: 39702
Terminal 2 : Vérifier en capturant les paquets avec tcpdump
$ sudo tcpdump host www.baidu.com -v tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes 18:38:32.381448 IP (tos 0x0, ttl 64, id 35033, offset 0, flags [DF], proto TCP (6), length 60) icentos.39702 > 220.181.111.188.http: Flags [S], cksum 0x8cd2 (incorrect -> 0x596a), seq 2381397554, win 29200, options [mss 1460,sackOK,TS val 3513497323 ecr 0,nop,wscale 7], length 0 18:38:32.425904 IP (tos 0x0, ttl 55, id 35033, offset 0, flags [DF], proto TCP (6), length 60) 220.181.111.188.http > icentos.39702: Flags [S.], cksum 0xc315 (correct), seq 3561856904, ack 2381397555, win 8192, options [mss 1424,sackOK,nop,nop,nop,nop,nop,nop,nop,nop,nop,nop,nop,wscale 5], length 0 18:38:32.425930 IP (tos 0x0, ttl 64, id 35034, offset 0, flags [DF], proto TCP (6), length 40)
La comparaison du terminal un et du terminal deux montre que l'adresse du port source obtenue est correcte.
Résumé
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!