我想在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);
}
}
}
感谢您的帮助。 电贺 托比
答案 0 :(得分:1)
有几点需要改进。
首先:目前还不清楚你想要保护什么。我会理解你是使用一个互斥锁来保护一个缓冲区,而另一个互斥锁是另一个缓冲区,所以每个缓冲区总是只能被一个线程访问。但是,这不会发生 - 两个线程都可以同时读取+写入相同的缓冲区。相反,每个互斥锁同时保护套接字不受读取和写入的影响,这是毫无意义的,因为套接字可以完美地处理它。您可以同时在同一个套接字上读取+写入。套接字用于实现这一目标已有30多年了。
一旦更改并且您的互斥锁保护缓冲区,您将再次遇到阻塞,但不常见。您将体验到一个线程在没有可用的情况下尝试读取或写入数据,或者套接字连接已满(如果您尝试快速写入大量数据,则会发生这种情况)并且传输数据需要时间。
这可以通过select()或者poll()来解决。因此,要走的路是:
每个线程使用select()或poll()来查明它是否可以读取或写入数据。只有它可以,它锁定缓冲区的互斥锁,然后读取或写入数据(在确定的select()或poll()之后不会阻塞,然后释放互斥锁。