C++ TCP代理和套接字编程
好吧,我在过去十个小时里(字面意思)搜索了网络,但似乎没有人有教程解释如何在 Windows 中创建 C++ 代理服务器。我曾多次遇到仅适用于 UNIX 的函数,这是一次令人沮丧的经历。我对套接字编程非常陌生,但我需要在 48 小时内完成。现在看来是不可能的。
程序要求:
- 守护程序侦听指定端口号上的 TCP 连接。
- 当新的客户端发起TCP连接请求时,守护进程接受 请求并与新客户端建立 TCP 连接。
- 守护进程派生一个子进程,专门用于处理新的 客户。
- 子进程与预先分配的端口建立 TCP 连接 实际目标服务器。
- 子进程陷入循环,在循环中它充当中介者 在客户端和客户端之间交换数据(读/写或写/读) 目标服务器。
- 一旦子进程被分叉,守护进程就会继续监听 额外的 TCP 连接。
我已经运行了提供的 winsock 客户端和程序,以更好地了解套接字的工作原理,但它让我一无所获。 pid_t
对于 Windows 不可用,因此不可能进行分叉(或者说我从 10 个小时的网络搜索中得出的结论)。
如果您能为我指明正确的方向,以便能够将 Internet Explorer 的代理设置(IP 和端口号功能)与该程序结合使用来生成重定向到另一台服务器的网页,那就太好了。
/* client.c - code for example client program that uses TCP */
#ifndef unix
#include<winsock2.h>
#include <windows.h>
#include <winsock.h>
#pragma comment(lib, "ws2_32.lib")
#else
#define closesocket close
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#endif
#include <stdio.h>
#include <string.h>
#include <iostream>
#define PROTOPORT 5193 /* default protocol port number */
extern "C";
char localhost[] = "localhost"; /* default host name */
#define QLEN 6 /* size of request queue */
int visits = 0; /* counts client connections */
/*------------------------------------------------------------------------
* Program: client
*
* Purpose: allocate a socket, connect to a server, and print all output
*
* Syntax: client [ host [port] ]
*
* host - name of a computer on which server is executing
* port - protocol port number server is using
*
* Note: Both arguments are optional. If no host name is specified,
* the client uses "localhost"; if no protocol port is
* specified, the client uses the default given by PROTOPORT.
*
*------------------------------------------------------------------------
*/
int main(int argc, char *argv[])
{
struct hostent *ptrh; /* pointer to a host table entry */
struct protoent *ptrp; /* pointer to a protocol table entry */
struct sockaddr_in sad; /* structure to hold an IP address */
int port; /* protocol port number */
char *host; /* pointer to host name */
int n; /* number of characters read */
char buf[1000]; /* buffer for data from the server */
struct sockaddr_in cad; /* structure to hold client's address */
int sd, sd2; /* socket descriptors */
int alen; /* length of address */
#ifdef WIN32
WSADATA wsaData;
WSAStartup(0x0101, &wsaData);
#endif
memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
sad.sin_family = AF_INET; /* set family to Internet */
sad.sin_addr.s_addr = INADDR_ANY; /* set the local IP address */
/* Check command-line argument for protocol port and extract */
/* port number if one is specified. Otherwise, use the default */
/* port value given by constant PROTOPORT */
if (argc > 2) { /* if protocol port specified */
port = atoi(argv[2]); /* convert to binary */
} else {
port = PROTOPORT; /* use default port number */
}
if (port > 0) /* test for legal value */
sad.sin_port = htons((u_short)port);
else { /* print error message and exit */
fprintf(stderr,"bad port number %s\n",argv[2]);
exit(1);
if (argc > 1) { /* if argument specified */
port = atoi(argv[1]); /* convert argument to binary */
} else {
port = PROTOPORT; /* use default port number */
}
if (port > 0) /* test for illegal value */
sad.sin_port = htons((u_short)port);
else { /* print error message and exit */
fprintf(stderr,"bad port number %s\n",argv[1]);
exit(1);
}
/* Map TCP transport protocol name to protocol number */
(int)(ptrp = getprotobyname("tcp"));
if ( ((int)(ptrp = getprotobyname("tcp"))) == 0) {
fprintf(stderr, "cannot map \"tcp\" to protocol number");
exit(1);
}
/* Check host argument and assign host name. */
if (argc > 1) {
host = argv[1]; /* if host argument specified */
} else {
host = localhost;
}
/* Convert host name to equivalent IP address and copy to sad. */
ptrh = gethostbyname(host);
if ( ((char *)ptrh) == NULL ) {
fprintf(stderr,"invalid host: %s\n", host);
exit(1);
}
memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length);
/* Map TCP transport protocol name to protocol number. */
(int)(ptrp = getprotobyname("tcp"));
if ( ((int)(ptrp = getprotobyname("tcp"))) == 0) {
fprintf(stderr, "cannot map \"tcp\" to protocol number");
exit(1);
}
/* Create a socket. */
sd = socket(PF_INET, SOCK_STREAM, ptrp->p_proto);
if (sd < 0) {
fprintf(stderr, "socket creation failed\n");
exit(1);
}
/* Connect the socket to the specified server. */
connect(sd, (struct sockaddr *)&sad, sizeof(sad));
if (connect(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr,"connect failed\n");
exit(1);
}
/* Bind a local address to the socket */
bind(sd, (struct sockaddr *)&sad, sizeof(sad));
if (bind(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr,"bind failed\n");
exit(1);
}
/* Specify size of request queue */
listen(sd, QLEN);
if (listen(sd, QLEN) < 0) {
fprintf(stderr,"listen failed\n");
exit(1);
}
/* Repeatedly read data from socket and write to user's screen. */
n = recv(sd, buf, sizeof(buf), 0);
while (n > 0) {
int _write(int fd, const void *buffer, unsigned int count);
n = recv(sd, buf, sizeof(buf), 0);
}
/* Main server loop - accept and handle requests */
while (1) {
alen = sizeof(cad);
printf("\nI'm waiting for connections ...");
fflush(stdout);
if ( (sd2=accept(sd, (struct sockaddr *)&cad, &alen)) < 0) {
fprintf(stderr, "accept failed\n");
exit(1);
}
printf("\nI received one connection.\n");
fflush(stdout);
visits++;
sprintf_s(buf,"This server has been contacted %d time%s\n",
visits,visits==1?".":"s.");
send(sd2,buf,strlen(buf),0);
printf("\nI sent the client a string.\n");
fflush(stdout);
closesocket(sd2);
}
/* Close the socket. */
closesocket(sd);
/* Terminate the client program gracefully. */
exit(0);
}
}
如果您已经做到了这一点,我感谢您的警惕。祝我好运...
Okay, I've scoured the net (literally) for the last ten hours, but no one seems to have a tutorial explaining how to create a C++ Proxy server in Windows. Several times I've run into functions that work solely for UNIX, and it's been a frustrating experience. I am VERY new to socket programming, but I need to have this finished within 48 hours. It seems impossible right now.
Requirements for the program:
- The daemon listens for TCP connections on a specified port number.
- When a new client initiates a TCP connection request, the daemon accepts
the request and establishes a TCP connection with the new client. - The daemon forks a child process that is dedicated to handling the new
client. - The child process establishes a TCP connection to a pre-assigned port on the
actual targeted server. - The child process falls into a loop in which it acts as an intermediator
exchanging data (reading/writing or writing/reading) between the client and
the targeted server. - Once a child has been forked, the daemon process resumes listening for
additional TCP connections.
I've run a provided winsock client and program to get a better idea of how sockets work, but it's getting me nowhere fast. pid_t
is unavailable for windows, so forking is out of the question (or so I've gathered from the 10 hours of net-scouring).
If you can point me in the right direction for being able to use Internet Explorer's proxy settings (the IP and Port number feature) in combination with the program to yield webpages that are redirected to another server, that would be great.
/* client.c - code for example client program that uses TCP */
#ifndef unix
#include<winsock2.h>
#include <windows.h>
#include <winsock.h>
#pragma comment(lib, "ws2_32.lib")
#else
#define closesocket close
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#endif
#include <stdio.h>
#include <string.h>
#include <iostream>
#define PROTOPORT 5193 /* default protocol port number */
extern "C";
char localhost[] = "localhost"; /* default host name */
#define QLEN 6 /* size of request queue */
int visits = 0; /* counts client connections */
/*------------------------------------------------------------------------
* Program: client
*
* Purpose: allocate a socket, connect to a server, and print all output
*
* Syntax: client [ host [port] ]
*
* host - name of a computer on which server is executing
* port - protocol port number server is using
*
* Note: Both arguments are optional. If no host name is specified,
* the client uses "localhost"; if no protocol port is
* specified, the client uses the default given by PROTOPORT.
*
*------------------------------------------------------------------------
*/
int main(int argc, char *argv[])
{
struct hostent *ptrh; /* pointer to a host table entry */
struct protoent *ptrp; /* pointer to a protocol table entry */
struct sockaddr_in sad; /* structure to hold an IP address */
int port; /* protocol port number */
char *host; /* pointer to host name */
int n; /* number of characters read */
char buf[1000]; /* buffer for data from the server */
struct sockaddr_in cad; /* structure to hold client's address */
int sd, sd2; /* socket descriptors */
int alen; /* length of address */
#ifdef WIN32
WSADATA wsaData;
WSAStartup(0x0101, &wsaData);
#endif
memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
sad.sin_family = AF_INET; /* set family to Internet */
sad.sin_addr.s_addr = INADDR_ANY; /* set the local IP address */
/* Check command-line argument for protocol port and extract */
/* port number if one is specified. Otherwise, use the default */
/* port value given by constant PROTOPORT */
if (argc > 2) { /* if protocol port specified */
port = atoi(argv[2]); /* convert to binary */
} else {
port = PROTOPORT; /* use default port number */
}
if (port > 0) /* test for legal value */
sad.sin_port = htons((u_short)port);
else { /* print error message and exit */
fprintf(stderr,"bad port number %s\n",argv[2]);
exit(1);
if (argc > 1) { /* if argument specified */
port = atoi(argv[1]); /* convert argument to binary */
} else {
port = PROTOPORT; /* use default port number */
}
if (port > 0) /* test for illegal value */
sad.sin_port = htons((u_short)port);
else { /* print error message and exit */
fprintf(stderr,"bad port number %s\n",argv[1]);
exit(1);
}
/* Map TCP transport protocol name to protocol number */
(int)(ptrp = getprotobyname("tcp"));
if ( ((int)(ptrp = getprotobyname("tcp"))) == 0) {
fprintf(stderr, "cannot map \"tcp\" to protocol number");
exit(1);
}
/* Check host argument and assign host name. */
if (argc > 1) {
host = argv[1]; /* if host argument specified */
} else {
host = localhost;
}
/* Convert host name to equivalent IP address and copy to sad. */
ptrh = gethostbyname(host);
if ( ((char *)ptrh) == NULL ) {
fprintf(stderr,"invalid host: %s\n", host);
exit(1);
}
memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length);
/* Map TCP transport protocol name to protocol number. */
(int)(ptrp = getprotobyname("tcp"));
if ( ((int)(ptrp = getprotobyname("tcp"))) == 0) {
fprintf(stderr, "cannot map \"tcp\" to protocol number");
exit(1);
}
/* Create a socket. */
sd = socket(PF_INET, SOCK_STREAM, ptrp->p_proto);
if (sd < 0) {
fprintf(stderr, "socket creation failed\n");
exit(1);
}
/* Connect the socket to the specified server. */
connect(sd, (struct sockaddr *)&sad, sizeof(sad));
if (connect(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr,"connect failed\n");
exit(1);
}
/* Bind a local address to the socket */
bind(sd, (struct sockaddr *)&sad, sizeof(sad));
if (bind(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr,"bind failed\n");
exit(1);
}
/* Specify size of request queue */
listen(sd, QLEN);
if (listen(sd, QLEN) < 0) {
fprintf(stderr,"listen failed\n");
exit(1);
}
/* Repeatedly read data from socket and write to user's screen. */
n = recv(sd, buf, sizeof(buf), 0);
while (n > 0) {
int _write(int fd, const void *buffer, unsigned int count);
n = recv(sd, buf, sizeof(buf), 0);
}
/* Main server loop - accept and handle requests */
while (1) {
alen = sizeof(cad);
printf("\nI'm waiting for connections ...");
fflush(stdout);
if ( (sd2=accept(sd, (struct sockaddr *)&cad, &alen)) < 0) {
fprintf(stderr, "accept failed\n");
exit(1);
}
printf("\nI received one connection.\n");
fflush(stdout);
visits++;
sprintf_s(buf,"This server has been contacted %d time%s\n",
visits,visits==1?".":"s.");
send(sd2,buf,strlen(buf),0);
printf("\nI sent the client a string.\n");
fflush(stdout);
closesocket(sd2);
}
/* Close the socket. */
closesocket(sd);
/* Terminate the client program gracefully. */
exit(0);
}
}
If you've made it this far, I thank you for your vigilance. Wish me luck...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论