我正在编写一个 tcp 代理,虽然它似乎可以工作,但它留下了内存泄漏。我操纵代码将传入的数据包转发给自己以创建 10000 个套接字并关闭它们以查看泄漏的位置。但是我无法弄清楚。我使用了 deleaker,它没有显示任何泄漏(除了一个我不在乎的小泄漏。)
任何帮助,将不胜感激!
代码:
#include <winsock2.h>
#include <stdio.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <tchar.h>
#include <process.h> /* _beginthread() */
// Need to link with Ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
#define PORT "1234" /* Port to listen on */
#define BUF_SIZE 4096 /* Buffer for transfers */
typedef struct {
char *host;
char *port;
SOCKET sock;
}
HandleStruct;
unsigned int S2C(SOCKET from, SOCKET to)
{
char buf[BUF_SIZE];
unsigned int disconnected = 0;
size_t bytes_read, bytes_written;
bytes_read = recv(from, buf, BUF_SIZE, 0);
if (bytes_read == 0) {
disconnected = 1;
}
else {
bytes_written = send(to, buf, bytes_read, 0);
if (bytes_written == -1) {
disconnected = 1;
}
}
return disconnected;
}
unsigned int C2S(SOCKET from, SOCKET to)
{
char buf[BUF_SIZE];
unsigned int disconnected = 0;
size_t bytes_read, bytes_written;
bytes_read = recv(from, buf, BUF_SIZE, 0);
if (bytes_read == 0) {
disconnected = 1;
}
else {
bytes_written = send(to, buf, bytes_read, 0);
if (bytes_written == -1) {
disconnected = 1;
}
}
return disconnected;
}
void handle(void *param)
{
HandleStruct *args = (HandleStruct*) param;
SOCKET client = args->sock;
const char *host = args->host;
const char *port = args->port;
SOCKET server = -1;
unsigned int disconnected = 0;
fd_set set;
unsigned int max_sock;
struct addrinfo *res = NULL;
struct addrinfo *ptr = NULL;
struct addrinfo hints;
/* Get the address info */
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if (getaddrinfo(host, port, &hints, &res) != 0) {
perror("getaddrinfo");
closesocket(client);
return;
}
/* Create the socket */
server = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (server == INVALID_SOCKET) {
perror("socket");
closesocket(client);
return;
}
/* Connect to the host */
if (connect(server, res->ai_addr, res->ai_addrlen) == -1) {
perror("connect");
closesocket(client);
return;
}
if (client > server) {
max_sock = client;
}
else {
max_sock = server;
}
/* Main transfer loop */
while (!disconnected) {
FD_ZERO(&set);
FD_SET(client, &set);
FD_SET(server, &set);
if (select(max_sock + 1, &set, NULL, NULL, NULL) == SOCKET_ERROR) {
perror("select");
break;
}
if (FD_ISSET(client, &set)) {
disconnected = C2S(client, server);
}
if (FD_ISSET(server, &set)) {
disconnected = S2C(server, client);
}
}
closesocket(server);
closesocket(client);
fprintf(stderr, "Sockets Closed: %d/%d", server, client);
_endthread();
return;
}
int _tmain(int argc)
{
WORD wVersion = MAKEWORD(2, 2);
WSADATA wsaData;
int iResult;
SOCKET sock;
struct addrinfo hints, *res;
int reuseaddr = 1; /* True */
/* Initialise Winsock */
if (iResult = (WSAStartup(wVersion, &wsaData)) != 0) {
fprintf(stderr, "WSAStartup failed: %dn", iResult);
return 1;
}
char * host = "127.0.0.1";
char * port = "1234";
/* Get the address info */
ZeroMemory(&hints, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(NULL, PORT, &hints, &res) != 0) {
perror("getaddrinfo");
WSACleanup();
return 1;
}
/* Create the socket */
sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sock == INVALID_SOCKET) {
perror("socket");
WSACleanup();
return 1;
}
/* Enable the socket to reuse the address */
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuseaddr,
sizeof(int)) == SOCKET_ERROR) {
perror("setsockopt");
WSACleanup();
return 1;
}
/* Bind to the address */
if (bind(sock, res->ai_addr, res->ai_addrlen) == SOCKET_ERROR) {
perror("bind");
WSACleanup();
return 1;
}
/* Listen */
if (listen(sock, 6500) == SOCKET_ERROR) {
perror("listen");
WSACleanup();
return 1;
}
freeaddrinfo(res);
int i = 0;
HandleStruct *arg;
arg = (HandleStruct *)malloc(sizeof( HandleStruct));
/* Main loop */
while(1) {
int size = sizeof(struct sockaddr);
struct sockaddr_in their_addr;
SOCKET newsock;
ZeroMemory(&their_addr, sizeof (struct sockaddr));
newsock = accept(sock, (struct sockaddr*)&their_addr, &size);
if (newsock == INVALID_SOCKET) {
perror("acceptn");
}
else {
arg->sock = newsock;
arg->host = host;
arg->port = port;
if (i < 10000) {
_beginthread(handle, 0, (void*) arg);
i++;
}
}
}
closesocket(sock);
WSACleanup();
return 0;
}