C++ SOCKET端口复用


-
复用端口的原理是用在服务器安装一个中间程序,在客户端发送数据给端口前劫获这个数据,判断这个是不是HACKER发来的数据,如果是把它发给后门程序,如果不是则转发给端口程序,返回信息再发给客户端.所以中间程序即是一个服务端程序(监听连接)也是一个客户端程序(发送给端口程序).要复用端口,必须使中间程序的监听SOCKET用setsockopt()函数设置.
-
2018-11-19
-
2014-03-25
-
2013-09-15
-
2013-05-02
-
2013-04-02
-
2013-03-14
-
2013-01-17
-
2012-12-11
-
2012-12-06
-
2012-10-26
socket编程端口复用问题_course
2014-12-03socket编程,想将几个客户端,绑定到同一个端口上,第一个可以绑定成功,第二个bind返回错误,errno=98(address already in use),我在socket选项里已经加上了,地
C++ socket端口复用的问题_course
2016-12-15环境 公网服务器1台,内网服务器若干。其中一台内网可以和公网连接通信,打算在公网上用socket做端口转发来实现访各台问内网的目的。功能已经实现了(一对一连接),但端口复用问题一直很困惑,请各位帮忙检查一下代码,谢谢 公网代码 ``` // 绑定两个服务器socket void bind2bind(int port1, int port2) { char msgbuf[100]; memset(msgbuf, 0, 100); sprintf(msgbuf, "[+] 服务器初始化...\r\n"); outprint(msgbuf, strlen(msgbuf)); int fd0, fd1, fd2; if ((fd0 = create_socket()) == 0) return; if ((fd1 = create_socket()) == 0) return; if ((fd2 = create_socket()) == 0) return; int port0 = 5501; if (create_server(fd0, port0) == 0) { closesocket(fd0); return; } sprintf(msgbuf, "[+] 成功监听通信端口: %d\r\n", port0); outprint(msgbuf, strlen(msgbuf)); // 创建第一个服务器 if (create_server(fd1, port1) == 0) { closesocket(fd1); return; } sprintf(msgbuf, "[+] 成功监听隧道端口: %d\r\n", port1); outprint(msgbuf, strlen(msgbuf)); // 创建第二个服务器 if (create_server(fd2, port2) == 0) { closesocket(fd2); return; } sprintf(msgbuf, "[+] 成功监听上线端口: %d\r\n", port2); outprint(msgbuf, strlen(msgbuf)); // 等待两端上线 while (1) { sprintf(msgbuf, "[%d] 正在建立通信端口: %d\r\n", idx, port0); outprint(msgbuf, strlen(msgbuf)); struct sockaddr_in client0; int size0 = sizeof(struct sockaddr); int sockfd0 = accept(fd0, (struct sockaddr *)&client0, &size0); sprintf(msgbuf, "[%d] 通信端口连接成功 IP地址: %s\r\n", idx, inet_ntoa(client0.sin_addr)); outprint(msgbuf, strlen(msgbuf)); sprintf(msgbuf, "[%d] 发送idx值: %d\r\n", idx, idx); outprint(msgbuf, strlen(msgbuf)); char idxbuf[10]; memset(idxbuf, 0, 10); sprintf(idxbuf, "%d", idx); int send0 = send(sockfd0, idxbuf, strlen(idxbuf)+1, 0); if (send0 <= 0) { closesocket(sockfd0); continue; } closesocket(sockfd0); sprintf(msgbuf, "[%d] 正在建立隧道端口: %d\r\n", idx, port1); outprint(msgbuf, strlen(msgbuf)); struct sockaddr_in client1; int size1 = sizeof(struct sockaddr); int sockfd1 = accept(fd1, (struct sockaddr *)&client1, &size1); sprintf(msgbuf, "[%d] 正在建立上线端口: %d\r\n", idx, port2); outprint(msgbuf, strlen(msgbuf)); struct sockaddr_in client2; int size2 = sizeof(struct sockaddr); int sockfd2 = accept(fd2, (struct sockaddr *)&client2, &size2); sprintf(msgbuf, "[%d] 通过上线端口连接成功 IP地址: %s\r\n", idx, inet_ntoa(client2.sin_addr)); outprint(msgbuf, strlen(msgbuf)); // socket transocket sock; sock.fd1 = sockfd1; sock.fd2 = sockfd2; sock.idx = idx; CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)transmitdata, (LPVOID)&sock, 0, NULL); idx++; } } ``` ``` 负责通信的内网代码 { int port0 = 5501; char msgbuf[100]; memset(msgbuf, 0, 100); while (1) { int sockfd0; if ((sockfd0 = create_socket()) == 0) return 0; // 通过5501端口连接服务器 sprintf(msgbuf, "[+] 正在连接服务器 %s:%d\r\n", sConnectHost, port0); outprint(msgbuf, strlen(msgbuf)); if (client_connect(sockfd0, sConnectHost, port0) == 0) { closesocket(sockfd0); continue; } sprintf(msgbuf, "[+] 服务器连接成功\r\n"); outprint(msgbuf, strlen(msgbuf)); // 接收服务器idx值 char idxbuf[10]; memset(idxbuf, 0, 10); int read0 = recv(sockfd0, idxbuf, 10, 0); if (read0 > 0) { // 在线程内执行conn2conn int nIdx = atoi(idxbuf); tranconn2conn conn; conn.host1 = sConnectHost; conn.port1 = iConnectPort; conn.host2 = sTransmitHost; conn.port2 = iTransmitPort; conn.idx = nIdx; CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)conn2conn, (LPVOID)&conn, 0, NULL); } } closeallfd(); } // 内网转发数据 void conn2conn(LPVOID data) { tranconn2conn *conn = (tranconn2conn *)data; char msgbuf[100]; memset(msgbuf, 0, 100); while (1) { int sockfd1, sockfd2; if ((sockfd1 = create_socket()) == 0) return; if ((sockfd2 = create_socket()) == 0) return; sprintf(msgbuf, "[%d] 正在连接服务器 %s:%d\r\n", conn->idx, conn->host1, conn->port1); outprint(msgbuf, strlen(msgbuf)); if (client_connect(sockfd1, conn->host1, conn->port1) == 0) { closesocket(sockfd1); closesocket(sockfd2); continue; } sprintf(msgbuf, "[%d] 服务器连接成功\r\n", conn->idx); outprint(msgbuf, strlen(msgbuf)); sprintf(msgbuf, "[%d] 正在连接内网 %s:%d\r\n", conn->idx, conn->host2, conn->port2); outprint(msgbuf, strlen(msgbuf)); if (client_connect(sockfd2, conn->host2, conn->port2) == 0) { closesocket(sockfd1); closesocket(sockfd2); continue; } sprintf(msgbuf, "[%d] 内网连接成功\r\n", conn->idx); outprint(msgbuf, strlen(msgbuf)); // socket transocket sock; sock.fd1 = sockfd1; sock.fd2 = sockfd2; sock.idx = conn->idx; transmitdata(&sock); } } ``` ``` 数据转发代码 // 服务器转发数据 void transmitdata(LPVOID data) { transocket *sock = (transocket *)data; // 准备采用select模型 fd_set readfd, writefd; char read_in1[MAXSIZE], send_out1[MAXSIZE]; char read_in2[MAXSIZE], send_out2[MAXSIZE]; struct sockaddr_in client1, client2; char host1[20], host2[20], msgbuf[100]; memset(host1, 0, 20); memset(host2, 0, 20); memset(msgbuf, 0, 100); int port1 = 0, port2 = 0; int structsize1 = sizeof(struct sockaddr); int structsize2 = sizeof(struct sockaddr); // 获取第一客户端信息 if (getpeername(sock->fd1, (struct sockaddr *)&client1, &structsize1) < 0) { strcpy(host1, "fd1"); } else { strcpy(host1, inet_ntoa(client1.sin_addr)); port1 = ntohs(client1.sin_port); } // 获取第二客户端信息 if (getpeername(sock->fd2, (struct sockaddr *)&client2, &structsize2) < 0) { strcpy(host2, "fd2"); } else { strcpy(host2, inet_ntoa(client2.sin_addr)); port2 = ntohs(client2.sin_port); } sprintf(msgbuf, "[%d] fd1: %d, fd2: %d\r\n", sock->idx, sock->fd1, sock->fd2); outprint(msgbuf, strlen(msgbuf)); // 输出两个客户端信息 sprintf(msgbuf, "[%d] 建立数据转发走向(%s:%d <-> %s:%d)\r\n", sock->idx, host1, port1, host2, port2); outprint(msgbuf, strlen(msgbuf)); // 最大检测数目 int maxfd = max(sock->fd1, sock->fd2) + 1; // 设置检测超时 struct timeval timeset; timeset.tv_sec = TIMEOUT; // 超时秒数 timeset.tv_usec = 0; // 超时微秒 // 位模式清零 memset(send_out1, 0, MAXSIZE); memset(send_out2, 0, MAXSIZE); // 可读长度 int totalread1 = 0, totalread2 = 0; while (1) { // 采用select异步模型 FD_ZERO(&readfd); FD_ZERO(&writefd); // 添加到fd集合 FD_SET(sock->fd1, &readfd); FD_SET(sock->fd1, &writefd); FD_SET(sock->fd2, &readfd); FD_SET(sock->fd2, &writefd); // 第一个参数会被系统忽略掉 int result = select(maxfd, &readfd, &writefd, NULL, ×et); if ((result < 0) && (errno != EINTR)) { // 程序出错 sprintf(msgbuf, "[%d] Error: select函数出错\r\n", sock->idx); outprint(msgbuf, strlen(msgbuf)); break; } else if (result == 0) { // 等待超时 sprintf(msgbuf, "[%d] Error: select函数等待超时\r\n", sock->idx); outprint(msgbuf, strlen(msgbuf)); continue; } // fd1可读, 只要可读, 一次即可读取完整, 无需while循环 if (FD_ISSET(sock->fd1, &readfd) && totalread1 < MAXSIZE) { int read1 = recv(sock->fd1, read_in1, MAXSIZE - totalread1, 0); if (read1 == 0 || (read1 < 0 && errno != EINTR)) { sprintf(msgbuf, "[%d] Error: 读取fd1出错\r\n", sock->idx); outprint(msgbuf, strlen(msgbuf)); break; } // 改变fd1的发送缓冲区和他的大小(接了就要发嘛) memcpy(send_out1 + totalread1, read_in1, read1); sprintf(msgbuf, "[%d] fd1成功在地址: %16s:%d上面读取%d字节\r\n", sock->idx, host1, port1, read1); outprint(msgbuf, strlen(msgbuf)); totalread1 += read1; memset(read_in1, 0, MAXSIZE); } // fd2可写 if (FD_ISSET(sock->fd2, &writefd)) { int err = 0; int sendcount1 = 0; // 发送的话可能一次发不完(数据包过大) while (totalread1 > 0) { int send1 = send(sock->fd2, send_out1+sendcount1, totalread1, 0); if (send1 == 0 || (send1 < 0 && errno != EINTR)) { sprintf(msgbuf, "[%d] Error: 写入fd2出错\r\n", sock->idx); outprint(msgbuf, strlen(msgbuf)); err = 1; break; } if ((send1 < 0) && (errno == ENOSPC)) break; // 改变缓冲区大小 sendcount1 += send1; totalread1 -= send1; sprintf(msgbuf, "[%d] fd2成功在地址: %16s:%d上面发送%d字节\r\n", sock->idx, host2, port2, send1); outprint(msgbuf, strlen(msgbuf)); } // 检验出错 if (err == 1) break; // 如果发送了数据, 并且没有发送干净 if ((totalread1 > 0) && (sendcount1 > 0)) { // 理论上下面两行永远不会执行 memcpy(send_out1, send_out1 + sendcount1, totalread1); memset(send_out1 + totalread1, 0, MAXSIZE - totalread1); } else { memset(send_out1, 0, MAXSIZE); } } // fd2可读, 只要可读, 一次即可读取完整, 无需while循环 if (FD_ISSET(sock->fd2, &readfd) && totalread2 < MAXSIZE) { int read2 = recv(sock->fd2, read_in2, MAXSIZE - totalread2, 0); if (read2 == 0 || (read2 < 0 && errno != EINTR)) { sprintf(msgbuf, "[%d] Error: 读取fd2出错\r\n", sock->idx); outprint(msgbuf, strlen(msgbuf)); break; } // 接了就立即发出去 memcpy(send_out2 + totalread2, read_in2, read2); sprintf(msgbuf, "[%d] fd2成功在地址: %16s:%d上面读取%d字节\r\n", sock->idx, host2, port2, read2); outprint(msgbuf, strlen(msgbuf)); totalread2 += read2; memset(read_in2, 0, MAXSIZE); } // fd1可写 if (FD_ISSET(sock->fd1, &writefd)) { int err2 = 0; int sendcount2 = 0; while (totalread2 > 0) { int send2 = send(sock->fd1, send_out2 + sendcount2, totalread2, 0); if (send2 == 0 || (send2 < 0 && errno != EINTR)) { sprintf(msgbuf, "[%d] Error: 写入fd1出错\r\n", sock->idx); outprint(msgbuf, strlen(msgbuf)); err2 = 1; break; } if ((send2 < 0) && (errno == ENOSPC)) break; sendcount2 += send2; totalread2 -= send2; sprintf(msgbuf, "[%d] fd1成功在地址: %16s:%d上面发送%d字节\r\n", sock->idx, host1, port1, send2); outprint(msgbuf, strlen(msgbuf)); } if (err2 == 1) break; if ((totalread2 > 0) && (sendcount2 > 0)) { memcpy(send_out2, send_out2+sendcount2, totalread2); memset(send_out2 + totalread2, 0, MAXSIZE - totalread2); } else { memset(send_out2, 0, MAXSIZE); } } } // 关闭socket closesocket(sock->fd1); closesocket(sock->fd2); sprintf(msgbuf, "[%d] 成功关闭掉两个socket, fd1, fd2\r\n", sock->idx); outprint(msgbuf, strlen(msgbuf)); sprintf(msgbuf, "[%d] 本次数据转发结束\r\n\n", sock->idx); outprint(msgbuf, strlen(msgbuf)); } ```
如何实现端口复用_course
2010-01-10Windows 2003 下如何实现端口复用 ,望高手解答
C++设置TCP端口重用(SetSockOpt )_course
2012-11-13#include "stdafx.h" #include <WinSock2.h> #include <Windows.h> #include <vector> #include <stdlib.h>
基于java的socket端口复用问题(TCP)_course
2015-03-12作为小白的我,想用本机的同一个端口与服务起的不同端口建立两个socket连接。在调用第二个cs2.bind()方法时,提示“Address already in use”地址已被使用,求大神指导。 注
UDP端口重用问题_course
2011-03-11在一台主机上同时运行三个程序,也就是同时开启三个进程,并将其绑定到同一个UDP端口,当其它主机发送UDP广播时,三个进程都能收到信息。而当其它主机向这台主机发送UDP单播时,只有一个进程收到信息,为什
TCP端口复用,同一个端口既listen又connect是否可行?_course
2018-10-29查阅了许多资料,端口复用是可行的。但是不知道是否可以既listen又connect? 大概思路: 1.创建两个socket, 2.都设置了setsockopt(accept_fd, SOL_SOCKE
多进程共用一个UDP端口问题_course
2007-04-11在BIND socket前,通过调用setsockopt()函数,设置成SO_REUSEADDR,这样端口就可以重用了 但是在客户端socket连接该端口时,只有一个进程响应,怎么才能使所有的监听指定
152.13MB
菜菜sklearn课程讲义.rar
2021-03-05适合正在学习机器学习sklearn库的使用教程,关注即可下载哦~
微信小程序样式开发入门
2019-01-07讲解微信小程序中样式的入门使用,如何使用传统的css知识点来开发wxss的样式;本节课主要讲解在微信小程序中创建样式的几种 写法,元素选择器的基础使用,id选择器和id派生选择器的使用,class类选择器的使用。
企业员工角色权限管理平台(SpringBoot2.0+Mybatis+Shiro+Vue)
2019-08-07课程简介: 历经半个多月的时间,Debug亲自撸的 “企业员工角色权限管理平台” 终于完成了。正如字面意思,本课程讲解的是一个真正意义上的、企业级的项目实战,主要介绍了企业级应用系统中后端应用权限的管理,其中主要涵盖了六大核心业务模块、十几张数据库表。 其中的核心业务模块主要包括用户模块、部门模块、岗位模块、角色模块、菜单模块和系统日志模块;与此同时,Debug还亲自撸了额外的附属模块,包括字典管理模块、商品分类模块以及考勤管理模块等等,主要是为了更好地巩固相应的技术栈以及企业应用系统业务模块的开发流程! 核心技术栈列表: 值得介绍的是,本课程在技术栈层面涵盖了前端和后端的大部分常用技术,包括Spring Boot、Spring MVC、Mybatis、Mybatis-Plus、Shiro(身份认证与资源授权跟会话等等)、Spring AOP、防止XSS攻击、防止SQL注入攻击、过滤器Filter、验证码Kaptcha、热部署插件Devtools、POI、Vue、LayUI、ElementUI、JQuery、HTML、Bootstrap、Freemarker、一键打包部署运行工具Wagon等等,如下图所示: 课程内容与收益: 总的来说,本课程是一门具有很强实践性质的“项目实战”课程,即“企业应用员工角色权限管理平台”,主要介绍了当前企业级应用系统中员工、部门、岗位、角色、权限、菜单以及其他实体模块的管理;其中,还重点讲解了如何基于Shiro的资源授权实现员工-角色-操作权限、员工-角色-数据权限的管理;在课程的最后,还介绍了如何实现一键打包上传部署运行项目等等。如下图所示为本权限管理平台的数据库设计图: 以下为项目整体的运行效果截图: 值得一提的是,在本课程中,Debug也向各位小伙伴介绍了如何在企业级应用系统业务模块的开发中,前端到后端再到数据库,最后再到服务器的上线部署运行等流程,如下图所示:
Java学习指南(Java入门与进阶)
2017-08-09这是Java学习指南系列课程的第1篇,介绍Java语言的入门语法,引领希望学习Java语言编程的初学者进入Java大门。 本课程不需要其他语言作为基础,可以直接学习。 课程从Java开发平台的下载和安装开始,从浅到深、从易到难,循序渐进地进行语法讲解。 为了让学员更好的掌握Java语言,本课程配套在线的Java题库及答案解析。 相比于其他语言,Java语言更科学、更容易掌握,快来和大家一起学习Java吧。
57.86MB
微信小程序源码-合集5.rar
2020-09-04微信小程序源码,包含:豆瓣、微信、论坛、停车、房贷计算、股票、蜗牛生活、物品回收、学车预约、住房装修、斗鱼直播、水利、快拍、同城等源码。
程序员的数学:微积分
2019-09-28本课程介绍程序员必备的数学基础内容,在取材上侧重人工智能、数据分析等热门领域
- 实时 摔倒识别 /运动分析/打架等异常行为识别/控制手势识别等所有行为识别全家桶 原理 + 代码 + 数据+ 模型 开源! 40522021-03-02文章目录一、 基本过程和思想二 、视频理解还有哪些优秀框架三、效果体验~使用手势:python run_gesture_recognition.py健身_跟踪器:卡路里计算三、训练自己数据集步骤然后,打开这个网址:点击一下start new project但是官方的制作方法是有着严重bug的~我们该怎么做呢!原代码解读 大家好,我是cv君,很多大创,比赛,项目,工程,科研,学术的炼丹术士问我上述这些识别,该怎么做,怎么选择框架,今天可以和大家分析一下一些方案: 用单帧目标检测做的话,前后语义相关性很差(也有
-
博客
进阶面试皆宜!阿里强推Java程序员进阶笔记,差距不止一点点
进阶面试皆宜!阿里强推Java程序员进阶笔记,差距不止一点点
-
下载
动产抵押合同.docx
动产抵押合同.docx
-
学院
CCNA_CCNP 思科网络认证 三层交换机(VTP 简化 VLAN
CCNA_CCNP 思科网络认证 三层交换机(VTP 简化 VLAN
-
下载
数据结构知识点复习.txt
数据结构知识点复习.txt
-
博客
c++变量初始化
c++变量初始化
-
博客
Polarized 3D翻译
Polarized 3D翻译
-
博客
centos7重启apache、nginx、mysql、php-fpm命令
centos7重启apache、nginx、mysql、php-fpm命令
-
博客
java绘制“五子棋棋盘”
java绘制“五子棋棋盘”
-
学院
Unity RUST 逆向安全开发
Unity RUST 逆向安全开发
-
学院
app软件测试全栈系列精品课程
app软件测试全栈系列精品课程
-
博客
ajax简介
ajax简介
-
学院
MySQL 数据类型和运算符
MySQL 数据类型和运算符
-
学院
xxljob源码分析
xxljob源码分析
-
学院
MySQL 事务和锁
MySQL 事务和锁
-
下载
liquibase-4.2.0.rar
liquibase-4.2.0.rar
-
下载
leetcode-study.zip
leetcode-study.zip
-
博客
IDEA全文搜索File mask设置后缀名属性
IDEA全文搜索File mask设置后缀名属性
-
学院
零基础极简以太坊智能合约开发环境搭建并开发部署
零基础极简以太坊智能合约开发环境搭建并开发部署
-
学院
计算机网络 静态路由和动态路由协议
计算机网络 静态路由和动态路由协议
-
学院
Android APP 性能和自动化测试框架精品课程
Android APP 性能和自动化测试框架精品课程
-
学院
MySQL 视图
MySQL 视图
-
学院
Docker核心技术进阶教程
Docker核心技术进阶教程
-
下载
【矢量图】指示灯图标库.zip
【矢量图】指示灯图标库.zip
-
下载
痛风的诊治PPT课件.ppt
痛风的诊治PPT课件.ppt
-
博客
VM设置52
VM设置52
-
博客
seata安装配置
seata安装配置
-
下载
05.ROS现状与应用实例.ppt
05.ROS现状与应用实例.ppt
-
下载
Doc12132.docx
Doc12132.docx
-
博客
浏览器缓存视频文件获取合并
浏览器缓存视频文件获取合并
-
学院
朱老师鸿蒙系列课程第1期-3.鸿蒙系统Harmonyos源码配置和管理
朱老师鸿蒙系列课程第1期-3.鸿蒙系统Harmonyos源码配置和管理