如何在C中存根套接字
How to stub a socket in C?
我已经编写了客户端代码,它应该通过套接字发送一些数据并从远程服务器读取答案。
我想对代码进行单元测试。函数的签名类似如下:
double call_remote(double[] args, int fd);
其中fd
为远程服务器的套接字的文件描述符。
现在,call_remote
函数在发送数据后,将阻止从服务器读取答案。如何存根这样一个远程服务器来对代码进行单元测试?
理想情况下,我希望是这样的:
int main() {
int stub = /* initialize stub */
double expected = 42.0;
assert(expected == call_remote(/* args */, stub);
return 0;
}
double stub_behavior(double[] args) {
return 42.0;
}
我希望调用stub_behavior
并将42.0
值发送到存根文件描述符。
如果这是POSIX系统,您可以使用fork()
和socketpair()
:
#define N_DOUBLES_EXPECTED 10
double stub_behaviour(double []);
int initialize_stub(void)
{
int sock[2];
double data[N_DOUBLES_EXPECTED];
socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
if (fork()) {
/* Parent process */
close(sock[0]);
return sock[1];
}
/* Child process */
close(sock[1]);
/* read N_DOUBLES_EXPECTED in */
read(sock[0], data, sizeof data);
/* execute stub */
data[0] = stub_behaviour(data);
/* write one double back */
write(sock[0], data, sizeof data[0]);
close(sock[0]);
_exit(0);
}
int main()
{
int stub = initialize_stub();
double expected = 42.0;
assert(expected == call_remote(/* args */, stub);
return 0;
}
double stub_behavior(double args[])
{
return 42.0;
}
…当然,您可能需要添加一些错误检查,并更改读取请求的逻辑。
socketpair()
创建的文件描述符是一个普通的套接字,因此像send()
和recv()
这样的套接字调用在它上面可以很好地工作。
您可以使用任何可以通过文件描述符访问的内容。一个文件或者,如果你想模拟阻塞行为,一个管道。
注意:显然套接字特定的调用(setsockopt, fcntl, ioctl,…)不会工作
我遇到了同样的情况,我将分享我的方法。我创建了网络转储,准确地记录了客户机应该发送的内容和服务器应该发送的响应内容。然后,我对客户机请求进行逐字节的比较,以确保它是匹配的。如果请求是有效的,则从响应文件中读取并将其发送回客户机。
我很高兴提供更多的细节(当我在一个机器访问这个代码)
这是一个c++实现(我知道,最初的问题是针对C的,但如果需要的话,很容易转换回C)。它可能不适用于非常大的字符串,因为如果字符串不能被缓冲,套接字可能会阻塞。但它适用于小单元测试。
/// Class creates a simple socket for testing out functions that write to a socket.
/// Usage:
/// 1. Call GetSocket() to get a file description socket ID
/// 2. write to that socket FD
/// 3. Call ReadAll() read back all the data that was written to that socket.
/// The sockets are all closed by ReadAll(), so this is a one-use object.
///
/// example
/// MockSocket ms;
/// int socket = ms.GetSocket();
/// send(socket,"foo bar",7);
/// ...
/// std::string s = ms.ReadAll();
/// EXPECT_EQ("foo bar",s);
class MockSocket
{
public:
~MockSocket()
{
}
int GetSocket()
{
socketpair(AF_UNIX, SOCK_STREAM, 0, sockets_);
return sockets_[0];
}
std::string ReadAll()
{
close(sockets_[0]);
std::string s;
char buffer[256];
while (true)
{
int n = read(sockets_[1], buffer, sizeof(buffer));
if (n > 0) s.append(buffer,n);
if (n <= 0) break;
}
close(sockets_[1]);
return s;
}
private:
int sockets_[2];
};
相关文章:
- 当套接字连接断开时检测C/C++Unix
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- 如何通过套接字将文本文件的内容从服务器发送到客户端
- 如何在C/C++中用FD_set Unix设置套接字文件描述符
- 套接字读取后,我在缓冲区中看到意外输入
- 如何在CPP中创建应该在Windows和Linux上运行的套接字?
- 我可以与 python 服务器而不是 c++ 客户端建立 tcp/ip 套接字吗?
- 套接字连接"Operation not permitted"错误,甚至使用升压/平发器根.cpp
- WINAPI 注册应用程序重新启动时不清除打开的套接字
- (Winsock) UDP 接收工作正常,但同一套接字的发送失败
- MSG_WAITALL的套接字发送得到了 22 EINVAL
- C++套接字客户端到 Python 服务器未创建连接
- 在不知道套接字的情况下关闭网络连接
- C++套接字对不读/写父/子
- 非更新套接字消息
- SIGSEGV on Boost UDP 套接字关闭 - tcache_get at malloc.c.
- 将"uint8_t"(从套接字读取)隐式转换为"char"安全吗
- 当对套接字 send() 的同步调用由于连接另一端丢失而被阻止时,如何恢复?
- 当客户端在 write() 期间终止连接时,由对等套接字错误重置连接
- 如何在C中存根套接字