Heim  >  Artikel  >  Betrieb und Instandhaltung  >  So implementieren Sie die Socket-Kommunikation, um die lokale Quellportnummer unter Linux zu erhalten

So implementieren Sie die Socket-Kommunikation, um die lokale Quellportnummer unter Linux zu erhalten

黄舟
黄舟Original
2017-09-29 11:15:052841Durchsuche

In diesem Artikel werden hauptsächlich relevante Informationen zur Linux-Socket-Kommunikation vorgestellt, um die lokale Quellportnummer zu erhalten.

Es gibt viele Informationen zur TCP-IP-Netzwerkkommunikation IP-Datenpakete. Modus für End-to-End-Kommunikation. Ein typisches TCP-Datenpaket sieht wie folgt aus:

Sie können sehen, dass das Datenpaket die Quellportnummer und die Zielportnummer enthält, wenn der Client-Socket eine Verbindung zum herstellt Server, das System gibt dem Socket eine zufällige Quellportnummer zu, und wir können die ursprünglichen Portinformationen des erfolgreich verbundenen Sockets über getocketname erhalten.

Funktionsprototyp


#include <sys/socket.h> 
int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

Parameter:

Handle der Sockfd-Socket-Verbindung

addr-Netzwerkadresszeiger, der zum Speichern lokaler Socket-Adressinformationen verwendet wird,

addrlen addr space size

Ergebnis zurückgeben. Wenn der Aufruf erfolgreich ist, geben Sie 0 zurück und speichern Sie die lokalen Netzwerkadressinformationen in In addr wird bei einem Fehler -1 zurückgegeben und Fehlerinformationen werden durch errno widergespiegelt.

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; 
 } 
}

Dieses Programm startet zunächst einen Socket, um eine Verbindung zu einem normalen http-Server herzustellen (Baidu, qq, 163, csdn). , Wenn der Socket verbunden ist, wird die an die Verbindung gebundene lokale Adresse über getsocketname und die Quellportnummer über diese Adresse abgerufen.

Terminal 1: Kompilieren und ausführen


$ g++ source_port.cpp
$ ./a.out www.baidu.com
connect to www.baidu.com success.
local port: 39702

Terminal 2: Überprüfen durch Erfassen von Paketen mit 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)

Der Vergleich von Terminal eins und Terminal zwei zeigt, dass die erhaltene Quell-Port-Adresse korrekt ist.

Zusammenfassung

Das obige ist der detaillierte Inhalt vonSo implementieren Sie die Socket-Kommunikation, um die lokale Quellportnummer unter Linux zu erhalten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn