TCP 代理 - 互斥量
TCP proxy - mutex
我想用 C++ 为大学编写一个简单的 TCP 代理。代理与两个线程一起工作,一个从源端口读取并写入目标端口,另一个线程在另一个方向做同样的事情。目的是在将来读取和操作数据包。如果我使用互斥锁锁定端口以在同一端口上进行读写,我会丢失包。你能帮我定位问题吗,因为我已经尝试了很长时间了?
thread1 = 0;
thread2 = 0;
//Client
struct sockaddr_in address;
int size;
if ((create_socket=socket (AF_INET, SOCK_STREAM, 0)) > 0)
printf ("Socket wurde angelegt\n");
address.sin_family = AF_INET;
address.sin_port = htons (PORT);
inet_aton (IP, &address.sin_addr);
if (connect ( create_socket, (struct sockaddr *) &address, sizeof (address)) == 0)
printf ("Verbindung mit dem Server (%s) hergestellt\n", inet_ntoa (address.sin_addr));
//Server
socklen_t addrlen;
struct sockaddr_in address2;
const int y = 1;
if ((create_socket2=socket (AF_INET, SOCK_STREAM, 0)) > 0)
printf ("Socket wurde angelegt\n");
setsockopt( create_socket2, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(int));
address2.sin_family = AF_INET;
address2.sin_addr.s_addr = INADDR_ANY;
address2.sin_port = htons (PORT2);
if (bind ( create_socket2, (struct sockaddr *) &address2, sizeof (address2)) != 0) {
printf( "Der Port ist nicht frei – belegt!\n");
}
listen (create_socket2, 5);
addrlen = sizeof (struct sockaddr_in);
new_socket2 = accept ( create_socket2, (struct sockaddr *) &address2, &addrlen );
if (new_socket2 > 0)
printf ("Ein Client (%s) ist verbunden ...\n", inet_ntoa (address2.sin_addr));
thread apm(apm_gcs);
thread gcs(gcs_apm);
apm.join();
gcs.join();
}
inline void apm_gcs()
{
while (STOP==FALSE)
{
{
lock_guard<mutex> lock(tcp60Mutex);
res = read(create_socket, buffer2, sizeof(buffer2)); // returns after 5 chars have been input
}
{
lock_guard<mutex> lock(tcp65Mutex);
write(new_socket2, buffer2, res);
}
}
}
inline void gcs_apm()
{
while (STOP==FALSE)
{
{
lock_guard<mutex> lock(tcp65Mutex);
res2 = read(new_socket2, buffer, sizeof(buffer)); // returns after 5 chars have been input
}
{
lock_guard<mutex> lock(tcp60Mutex);
write(create_socket, buffer, res2);
}
}
}
感谢您的帮助。
问候
托比
有几处需要改进。
首先:不清楚你到底想保护什么。如果您使用一个互斥量来保护一个缓冲区,而使用另一个互斥量来保护另一个缓冲区,我会理解,因此每个缓冲区将始终仅由一个线程访问。然而,这并没有发生——两个线程可以同时读+写同一个缓冲区。相反,每个互斥锁同时保护一个套接字不被读+写,这是没有意义的,因为套接字可以完美地处理它。您可以同时在同一个套接字上读+写。套接字用于此操作已有 30 多年了。
一旦更改并且您的互斥锁保护缓冲区,您将 运行 再次阻塞,尽管频率较低。你会体验到一个线程在 none 可用时尝试读取或写入数据,或者套接字连接已满(如果你试图快速写入大量数据会发生这种情况)并且传输数据需要时间。
这可以通过 select() 或者 poll() 来解决。因此要走的路是:
每个线程使用 select() 或 poll() 来确定它是否可以读取或写入数据。只有在可以的情况下,它才会锁定缓冲区的互斥量,然后读取或写入数据(在 select() 或 poll() 确定后不会阻塞),然后释放互斥量。
我想用 C++ 为大学编写一个简单的 TCP 代理。代理与两个线程一起工作,一个从源端口读取并写入目标端口,另一个线程在另一个方向做同样的事情。目的是在将来读取和操作数据包。如果我使用互斥锁锁定端口以在同一端口上进行读写,我会丢失包。你能帮我定位问题吗,因为我已经尝试了很长时间了?
thread1 = 0;
thread2 = 0;
//Client
struct sockaddr_in address;
int size;
if ((create_socket=socket (AF_INET, SOCK_STREAM, 0)) > 0)
printf ("Socket wurde angelegt\n");
address.sin_family = AF_INET;
address.sin_port = htons (PORT);
inet_aton (IP, &address.sin_addr);
if (connect ( create_socket, (struct sockaddr *) &address, sizeof (address)) == 0)
printf ("Verbindung mit dem Server (%s) hergestellt\n", inet_ntoa (address.sin_addr));
//Server
socklen_t addrlen;
struct sockaddr_in address2;
const int y = 1;
if ((create_socket2=socket (AF_INET, SOCK_STREAM, 0)) > 0)
printf ("Socket wurde angelegt\n");
setsockopt( create_socket2, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(int));
address2.sin_family = AF_INET;
address2.sin_addr.s_addr = INADDR_ANY;
address2.sin_port = htons (PORT2);
if (bind ( create_socket2, (struct sockaddr *) &address2, sizeof (address2)) != 0) {
printf( "Der Port ist nicht frei – belegt!\n");
}
listen (create_socket2, 5);
addrlen = sizeof (struct sockaddr_in);
new_socket2 = accept ( create_socket2, (struct sockaddr *) &address2, &addrlen );
if (new_socket2 > 0)
printf ("Ein Client (%s) ist verbunden ...\n", inet_ntoa (address2.sin_addr));
thread apm(apm_gcs);
thread gcs(gcs_apm);
apm.join();
gcs.join();
}
inline void apm_gcs()
{
while (STOP==FALSE)
{
{
lock_guard<mutex> lock(tcp60Mutex);
res = read(create_socket, buffer2, sizeof(buffer2)); // returns after 5 chars have been input
}
{
lock_guard<mutex> lock(tcp65Mutex);
write(new_socket2, buffer2, res);
}
}
}
inline void gcs_apm()
{
while (STOP==FALSE)
{
{
lock_guard<mutex> lock(tcp65Mutex);
res2 = read(new_socket2, buffer, sizeof(buffer)); // returns after 5 chars have been input
}
{
lock_guard<mutex> lock(tcp60Mutex);
write(create_socket, buffer, res2);
}
}
}
感谢您的帮助。 问候 托比
有几处需要改进。
首先:不清楚你到底想保护什么。如果您使用一个互斥量来保护一个缓冲区,而使用另一个互斥量来保护另一个缓冲区,我会理解,因此每个缓冲区将始终仅由一个线程访问。然而,这并没有发生——两个线程可以同时读+写同一个缓冲区。相反,每个互斥锁同时保护一个套接字不被读+写,这是没有意义的,因为套接字可以完美地处理它。您可以同时在同一个套接字上读+写。套接字用于此操作已有 30 多年了。
一旦更改并且您的互斥锁保护缓冲区,您将 运行 再次阻塞,尽管频率较低。你会体验到一个线程在 none 可用时尝试读取或写入数据,或者套接字连接已满(如果你试图快速写入大量数据会发生这种情况)并且传输数据需要时间。
这可以通过 select() 或者 poll() 来解决。因此要走的路是:
每个线程使用 select() 或 poll() 来确定它是否可以读取或写入数据。只有在可以的情况下,它才会锁定缓冲区的互斥量,然后读取或写入数据(在 select() 或 poll() 确定后不会阻塞),然后释放互斥量。