- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我在使用recv 函数时遇到问题
我有一个从客户端发送一些数据的应用程序,这些数据由服务器接收并根据数据发送响应。
当我发送少于 ~16 个请求时,实现工作正常。但是当我从客户端发送超过 16 个请求(一个接一个)时,服务器的响应很好,直到第 16 个请求,但在此之后服务器挂起。我可以看到数据是从客户端传输的,但服务器没有接收到。我正在使用函数 recv
接收发生在一个循环中,只有当从客户端收到终止请求时才会退出。
服务器代码:
// Request Winsock version 2.2
fprintf(stderr,"Performing WSAStartup\n");
if ((retval = WSAStartup(0x202, &wsaData)) != 0)
{
fprintf(stderr,"FAILED with error %d\n", retval);
WSACleanup();
return -1;
}
else
{
printf("OK\n");
}
if (port == 0)
{
Usage(argv[0]);
}
/* open socket connection */
printf("Opening socket\n");
local.sin_family = AF_INET;
local.sin_addr.s_addr = (!ip_address) ? INADDR_ANY:inet_addr(ip_address);
/* Port MUST be in Network Byte Order */
local.sin_port = htons(port);
// TCP socket
listen_socket = socket(AF_INET, socket_type,0);
if (listen_socket == INVALID_SOCKET){
fprintf(stderr,"socket() failed with error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
{
printf("OK\n");
}
// bind() associates a local address and port combination with the socket just created.
// This is most useful when the application is a
// server that has a well-known port that clients know about in advance.
printf("Bind address and port to socket\n");
if (bind(listen_socket, (struct sockaddr*)&local, sizeof(local)) == SOCKET_ERROR)
{
fprintf(stderr,"bind() failed with error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
{
printf("OK\n");
}
// So far, everything we did was applicable to TCP as well as UDP.
// However, there are certain steps that do not work when the server is
// using UDP. We cannot listen() on a UDP socket.
if (socket_type != SOCK_DGRAM)
{
printf("TCP: listening on socket\n");
if (listen(listen_socket,5) == SOCKET_ERROR)
{
fprintf(stderr,"listen() failed with error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
{
printf("OK\n");
}
}
//Perform Applcation task
//initisations
printf("Server is listening and waiting for a connection\non port %d, protocol %s\n",port, (socket_type == SOCK_STREAM)?"TCP":"UDP");
executeServer = 1;
while(executeServer == 1)
{
fromlen =sizeof(from);
// accept() doesn't make sense on UDP, since we do not listen()
if (socket_type != SOCK_DGRAM)
{
printf("TCP: Waiting for connection (accept())\n");
msgsock = accept(listen_socket, (struct sockaddr*)&from, &fromlen);
if (msgsock == INVALID_SOCKET)
{
fprintf(stderr,"accept() error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
{
printf("OK\n");
printf("accepted connection from %s, port %d\n", inet_ntoa(from.sin_addr), htons(from.sin_port)) ;
}
}
else
{
msgsock = listen_socket;
}
// In the case of SOCK_STREAM, the server can do recv() and send() on
// the accepted socket and then close it.
// However, for SOCK_DGRAM (UDP), the server will do recvfrom() and sendto() in a loop.
printf("Receiving data");
if (socket_type != SOCK_DGRAM)
{
retval = recv(msgsock, Buffer, sizeof(Buffer), 0);
}
else
{
retval = recvfrom(msgsock,Buffer, sizeof(Buffer), 0, (struct sockaddr *)&from, &fromlen);
printf("Received datagram from %s\n", inet_ntoa(from.sin_addr));
}
if (retval == SOCKET_ERROR)
{
fprintf(stderr,"recv() failed: error %d\n", WSAGetLastError());
closesocket(msgsock);
return -2;
}
else
{
printf("OK\n");
}
if (retval == 0)
{
printf("Client closed connection.\n");
closesocket(msgsock);
}
else
{
printf("Received %d bytes, data \"%s\" from client\n", retval, Buffer);
}
printf("Processing Data\n");
if (!stricmp(Buffer, "exit"))
{
wsprintf(AckBuffer,"ACK");
executeServer = 0;
}
else
{
// Perform use task here based on recieved data
}
printf("Sending answer to client\n");
if (socket_type != SOCK_DGRAM)
{
retval = send(msgsock, AckBuffer, sizeof(AckBuffer), 0);
}
else
{
retval = sendto(msgsock, AckBuffer, sizeof(AckBuffer), 0, (struct sockaddr *)&from, fromlen);
}
if (retval == SOCKET_ERROR)
{
fprintf(stderr,"send() failed: error %d\n", WSAGetLastError());
}
else
{
printf("OK\n");
}
/* close TCP connection */
if (socket_type != SOCK_DGRAM)
{
closesocket(msgsock);
}
}
printf("terminating server\n");
closesocket(msgsock);
WSACleanup();
客户端代码:
fprintf(stderr,"Performing WSAStartup");
if ((retval = WSAStartup(0x202, &wsaData)) != 0)
{
fprintf(stderr,"WSAStartup() failed with error %d\n", retval);
WSACleanup();
return -1;
}
else
{
printf("OK\n");
}
if (port == 0)
{
Usage(argv[0]);
}
// Attempt to detect if we should call gethostbyname() or gethostbyaddr()
printf("Translate hastname to address -> gethostbyaddr()\n");
if (isalpha(server_name[0]))
{ // server address is a name
hp = gethostbyname(server_name);
}
else
{ // Convert nnn.nnn address to a usable one
addr = inet_addr(server_name);
hp = gethostbyaddr((char *)&addr, 4, AF_INET);
}
if (hp == NULL )
{
fprintf(stderr,"Cannot resolve address \"%s\": Error %d\n", server_name, WSAGetLastError());
WSACleanup();
exit(1);
}
else
{
printf("OK\n");
}
// Copy the resolved information into the sockaddr_in structure
printf("Opening socket\n");
memset(&server, 0, sizeof(server));
memcpy(&(server.sin_addr), hp->h_addr, hp->h_length);
server.sin_family = hp->h_addrtype;
server.sin_port = htons(port);
conn_socket = socket(AF_INET, socket_type, 0); /* Open a socket */
if (conn_socket <0 )
{
fprintf(stderr,"Error Opening socket: Error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
{
printf("OK\n");
}
// Notice that nothing in this code is specific to whether we
// are using UDP or TCP.
// We achieve this by using a simple trick.
// When connect() is called on a datagram socket, it does not
// actually establish the connection as a stream (TCP) socket
// would. Instead, TCP/IP establishes the remote half of the
// (LocalIPAddress, LocalPort, RemoteIP, RemotePort) mapping.
// This enables us to use send() and recv() on datagram sockets,
// instead of recvfrom() and sendto()
printf("Client connecting to: %s.\n", hp->h_name);
if (connect(conn_socket, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
{
fprintf(stderr,"connect() failed: %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
{
printf("OK\n");
}
/* copy options string to buffer */
strcpy(Buffer,Options);
printf("Sending Data \"%s\"\n", Buffer);
retval = send(conn_socket, Buffer, sizeof(Buffer), 0);
if (retval == SOCKET_ERROR)
{
fprintf(stderr,"send() failed: error %d.\n", WSAGetLastError());
WSACleanup();
return -1;
}
else
{
printf("OK\n");
}
printf("Receiving status from server\n");
retval = recv(conn_socket, Buffer, sizeof(Buffer), 0);
if (retval == SOCKET_ERROR)
{
fprintf(stderr,"recv() failed: error %d.\n", WSAGetLastError());
closesocket(conn_socket);
WSACleanup();
return -1;
}
else
{
printf("OK\n");
}
// We are not likely to see this with UDP, since there is no
// 'connection' established.
if (retval == 0)
{
printf("Client: Server closed connection.\n");
closesocket(conn_socket);
WSACleanup();
return -1;
}
printf("Received %d bytes, data \"%s\" from server.\n", retval, Buffer);
closesocket(conn_socket);
WSACleanup();
最佳答案
如果您使用recv
时没有将套接字设置为非阻塞模式,那么您的recv
是正确的。它会阻塞,直到有内容可读为止。
[更新]
从代码来看,您确实使用了阻塞套接字。我建议您至少为您的服务器使用非阻塞套接字。我相信您可以轻松地通过谷歌搜索如何在 Windows 中制作非阻塞套接字和处理异步 IO。祝你好运!
[更新2]
首先,您的服务器代码似乎在 recv
读取内容后关闭连接。由于 TCP 不关心数据边界,您不能只关闭连接。请记住,客户端中的一次 send
调用可能需要在服务器中使用 TCP 进行多次 recv
调用,反之亦然。
对于您的具体问题,我很确定没有什么可读的,这就是 recv
阻止您的程序的原因。确保您的客户真的成功发送了一些东西。
关于c++ - 套接字编程 C/C++ - recv 函数在服务器中挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7314909/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!