21xrx.com
2024-12-22 23:27:46 Sunday
登录
文章检索 我的文章 写文章
C++ 网络编程:实现端口转发
2023-06-27 07:32:58 深夜i     --     --
C++ 网络编程 端口转发 实现 编程技能

随着互联网的不断发展,网络编程越来越重要。而在现实场景中,经常涉及到需要将一个端口通过网络转发到另外一个端口的情况,比如说内网穿透。本文将介绍如何使用C++进行网络编程实现端口转发。

首先,需要了解一些基本的网络编程知识,如什么是TCP和UDP。TCP是一种面向连接的协议,它保证数据传输的可靠性;UDP则是一种无连接的协议,它注重数据传输的速度。在实际应用中,通常使用TCP进行端口转发。

具体而言,我们需要实现一个客户端和服务端,客户端负责将原本要连接的端口连接到服务端,而服务端则将数据转发到目标端口。以下是一个简单的代码实现:

服务端


#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <errno.h>

#include <arpa/inet.h>

#include <netinet/ip.h>

#include <netinet/tcp.h>

#include <sys/socket.h>

#include <sys/types.h>

int main(int argc, char *argv[])

{

  if (argc != 3) {

    printf("Usage: %s listen_port forward_port\n", argv[0]);

    return -1;

  }

  int server_sock = socket(AF_INET, SOCK_STREAM, 0); // 创建服务端socket

  if (server_sock == -1) {

    perror("socket");

    return -1;

  }

  struct sockaddr_in server_addr, client_addr, forward_addr;

  memset(&server_addr, 0, sizeof(server_addr));

  memset(&client_addr, 0, sizeof(client_addr));

  memset(&forward_addr, 0, sizeof(forward_addr));

  server_addr.sin_family = AF_INET;

  server_addr.sin_port = htons(atoi(argv[1]));

  server_addr.sin_addr.s_addr = INADDR_ANY;

  if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { // 绑定端口

    perror("bind");

    return -1;

  }

  if (listen(server_sock, 10) == -1) { // 监听

    perror("listen");

    return -1;

  }

  int client_sock;

  socklen_t client_addr_len = sizeof(client_addr);

  while (1) {

    client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &client_addr_len); // 接收客户端连接

    if (client_sock == -1) {

      perror("accept");

      return -1;

    }

    int forward_sock = socket(AF_INET, SOCK_STREAM, 0); // 创建一个新socket,用于连接到转发端口

    if (forward_sock == -1) {

      perror("socket");

      return -1;

    }

    forward_addr.sin_family = AF_INET;

    forward_addr.sin_port = htons(atoi(argv[2]));

    forward_addr.sin_addr.s_addr = INADDR_ANY;

    if (connect(forward_sock, (struct sockaddr *)&forward_addr, sizeof(forward_addr)) == -1) { // 连接到目标端口

      perror("connect");

      return -1;

    }

    int pid = fork(); // 创建子进程

    if (pid == -1) {

      perror("fork");

    } else if (pid == 0) { // 子进程

      close(server_sock);

      char buf[4096];

      int n;

      while ((n = recv(client_sock, buf, sizeof(buf), 0)) > 0) { // 接收客户端数据并转发到目标端口

        if (send(forward_sock, buf, n, 0) == -1) {

          perror("send");

          break;

        }

      }

      close(client_sock);

      close(forward_sock);

      exit(0);

    } else { // 父进程

      close(client_sock);

      close(forward_sock);

    }

  }

  return 0;

}

客户端


#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <errno.h>

#include <arpa/inet.h>

#include <netinet/ip.h>

#include <netinet/tcp.h>

#include <sys/socket.h>

#include <sys/types.h>

#include <netdb.h>

int main(int argc, char *argv[])

{

  if (argc != 4) {

    printf("Usage: %s server_ip server_port forward_port\n", argv[0]);

    return -1;

  }

  int client_sock = socket(AF_INET, SOCK_STREAM, 0); // 创建客户端socket

  if (client_sock == -1) {

    perror("socket");

    return -1;

  }

  struct sockaddr_in server_addr, forward_addr;

  memset(&server_addr, 0, sizeof(server_addr));

  memset(&forward_addr, 0, sizeof(forward_addr));

  server_addr.sin_family = AF_INET;

  server_addr.sin_port = htons(atoi(argv[2]));

  struct hostent *he;

  if ((he = gethostbyname(argv[1])) == NULL) { // 解析服务器IP地址

    perror("gethostbyname");

    return -1;

  }

  memcpy(&server_addr.sin_addr, he->h_addr, he->h_length);

  if (connect(client_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { // 连接到服务端

    perror("connect");

    return -1;

  }

  int forward_sock = socket(AF_INET, SOCK_STREAM, 0); // 创建一个新socket,用于连接到转发端口

  if (forward_sock == -1) {

    perror("socket");

    return -1;

  }

  forward_addr.sin_family = AF_INET;

  forward_addr.sin_port = htons(atoi(argv[3]));

  forward_addr.sin_addr.s_addr = INADDR_ANY;

  if (connect(forward_sock, (struct sockaddr *)&forward_addr, sizeof(forward_addr)) == -1) { // 连接到目标端口

    perror("connect");

    return -1;

  }

  char buf[4096];

  int n;

  while ((n = recv(client_sock, buf, sizeof(buf), 0)) > 0) { // 接收服务端数据并转发到目标端口

    if (send(forward_sock, buf, n, 0) == -1) {

      perror("send");

      break;

    }

  }

  close(client_sock);

  close(forward_sock);

  return 0;

}

以上代码仅供学习参考,实际应用中需要考虑更多的因素,比如说错误处理、多线程优化等。这里仅是一个简单的示例,感兴趣的读者可以在此基础上进行更加自由的拓展实现。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复