- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我刚刚阅读了 recv
手册,但我在理解手册中的内容以及我的程序中实际发生的事情时遇到了一些问题。
手册说:
RETURN VALUE
... return the number of bytes received, or -1 if an error occurred.
所以我有以下可以编译和测试的程序:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define PORT 8888
#define MAX_LEN_MSG 50
#define BACKLOG 5
int socket_sckt ( struct sockaddr_in *server );
int bind_sckt ( struct sockaddr_in *server, const size_t server_addr_len );
int listen_sckt ( void );
int accept_sckt ( struct sockaddr_in *client, const size_t *client_addr_len );
int getsockname_sckt ( struct sockaddr_in *server, const size_t *server_addr_len );
int getpeername_sckt ( struct sockaddr_in *client, const size_t *client_addr_len );
ssize_t recv_sckt ( char *const msg );
int serverID;
int clientID;
int main( void )
{
char msg[ MAX_LEN_MSG] = { 0 };
struct sockaddr_in server;
struct sockaddr_in client;
size_t server_addr_len = sizeof( server );
size_t client_addr_len = sizeof( client );
memset( &server, 0, server_addr_len);
memset( &client, 0, client_addr_len);
/// Socket, Bind and Listen
serverID = socket_sckt ( &server );
bind_sckt ( &server, server_addr_len );
listen_sckt( );
getsockname_sckt( &server, &server_addr_len );
printf("Start Server on...\n" );
clientID = accept_sckt ( &client, &client_addr_len );
getpeername_sckt( &client, &client_addr_len );
printf("Connected IP(%s) on Port(%d)\n", inet_ntoa( client.sin_addr), ntohs( client.sin_port));
ssize_t recv_ret = recv_sckt ( msg );
if ( recv_ret > 0 )
{
printf("The MSG is %s | Len = %zu\n", msg, strlen( msg ) );
printf("The recived length is %zd\n", recv_ret );
}
}
int socket_sckt ( struct sockaddr_in *server )
{
int socket_ret = socket( AF_INET , SOCK_STREAM , 0);
if ( socket_ret == -1 )
{
printf( "Error, socket()\n" );
fprintf( stderr, "socket: %s (%d)\n", strerror( errno ), errno );
exit( EXIT_FAILURE );
}
server->sin_family = AF_INET;
server->sin_addr.s_addr = INADDR_ANY;
server->sin_port = htons( PORT );
return socket_ret;
}
int bind_sckt ( struct sockaddr_in *server, const size_t server_addr_len )
{
int bind_ret = bind( serverID, ( struct sockaddr * )server, ( socklen_t )server_addr_len );
if ( bind_ret == -1 )
{
printf( "Error, bind()\n" );
fprintf( stderr, "bind: %s (%d)\n", strerror( errno ), errno);
exit ( EXIT_FAILURE );
}
return bind_ret;
}
int listen_sckt ( void )
{
int listen_ret = listen( serverID, BACKLOG );
if ( listen_ret == -1 )
{
printf( "Error, listen()\n" );
fprintf( stderr, "listen: %s (%d)\n", strerror( errno ), errno );
exit( EXIT_FAILURE );
}
return listen_ret;
}
int accept_sckt ( struct sockaddr_in *client, const size_t *client_addr_len )
{
int accept_ret = accept( serverID, (struct sockaddr*) client, (socklen_t*) client_addr_len);
if ( accept_ret == -1 )
{
printf( "Error, accept()\n" );
fprintf( stderr, "accept: %s (%d)\n", strerror( errno ), errno );
exit( EXIT_FAILURE );
}
return accept_ret;
}
int getsockname_sckt ( struct sockaddr_in *server, const size_t *server_addr_len )
{
int getsockname_sckt = getsockname( serverID, ( struct sockaddr* ) server, ( socklen_t* ) server_addr_len );
if ( getsockname_sckt == -1 )
{
printf( "Error, getsockname()\n" );
fprintf( stderr, "getsockname: %s (%d)\n", strerror( errno ), errno );
exit ( EXIT_FAILURE );
}
return getsockname_sckt;
}
int getpeername_sckt ( struct sockaddr_in *client, const size_t *client_addr_len )
{
int getpeername_ret = getpeername( clientID, ( struct sockaddr* ) client, ( socklen_t* ) client_addr_len );
if ( getpeername_ret == -1 )
{
printf( "Error, getpeername()\n" );
fprintf( stderr, "getpeername: %s (%d)\n", strerror( errno ), errno );
exit ( EXIT_FAILURE );
}
return getpeername_ret;
}
ssize_t recv_sckt ( char *const msg )
{
ssize_t recv_ret = recv( clientID, msg, MAX_LEN_MSG, 0 );
if ( recv_ret == -1 )
{
printf( "Error, recv()\n" );
fprintf( stderr, "recv: %s (%d)\n", strerror( errno ), errno );
exit( EXIT_FAILURE );
}
msg[ strcspn( msg, "\n" ) ] = 0;
msg[ recv_ret ] = 0;
return recv_ret;
}
现在,如果我使用客户端连接到此服务器:
Please enter your name: George
Connect to Server: 192.168.0.103:8888
You are: 192.168.0.103:60878
在服务器端我得到:
Start Server on...
Connected IP(192.168.0.103) on Port(60878)
The MSG is George | Len = 6
The recived length is 31
为什么接收到的长度是31
而不是6
?
最佳答案
recv()
函数不会\0
终止缓冲区,在 recv_sckt()
函数中将缓冲区清零。
ssize_t recv_sckt ( char *const msg )
{
// Zero out the buffer
memset(msg, '\0', MAX_LEN_MEG);
ssize_t recv_ret = recv( clientID, msg, MAX_LEN_MSG, 0 );
if ( recv_ret == -1 )
{
printf( "Error, recv()\n" );
fprintf( stderr, "recv: %s (%d)\n", strerror( errno ), errno );
exit( EXIT_FAILURE );
}
msg[ strcspn( msg, "\n" ) ] = 0;
msg[ recv_ret ] = 0;
return recv_ret;
}
更新:
啊啊啊,我刚刚意识到 - msg[strcspn(msg, '\n')] = 0;
行将第一个 \n
替换为 0 (或 \0
)。
所以实际上它使缓冲区的一部分不可读。
也许不是
return recv_ret;
尝试:
return strlen(msg);
希望这能解决问题,我不确定服务器实际发送给您的是什么。
另一种方法可能是删除 msg[strcspn(msg, '\n')] = 0;
行,尽管我不确定 \n
所以可能会产生不希望的结果。
此外,您仍然需要确保正确终止缓冲区。
更新#2
我不确定服务器及其发送的内容,我指出的那一行:
msg[strcspn(msg, '\n')] = 0;`
基本上是在返回缓冲区中找到第一个 \n
字符并将其转换为 0 或 \0
字符。 \0
告诉像 printf()
这样的函数缓冲区在哪里结束。
但是,recv()
函数会返回一个数字,告诉您接收到的字节数。为了参数的缘故,让我们假设服务器正在返回这个字符串:
George\nabcdef
msg[strcspn(msg, '\n')] = 0;
行发现 \n
并将其替换为 \0
(或文字 0 值)。
所以 recv()
告诉你,嘿,看 - 我实际上读取了 13
字节,但是你让其中一些字节不可访问,因为它们超出了 >\0
终止符。
您会在 SO 和 Google 搜索中找到大量关于 c 中字符串终止的内容。您可以按照我在最初的回复中所说的那样做,并以零终止整个缓冲区:
memset(msg, '\0', buffer_size);
为了使数据以零结尾,我会尝试 - 删除 msg[strcspn(msg, '\n')] = 0;
行并打印出完整的缓冲区,包括\n
以及它之外的任何东西,也许是垃圾,也许只是空白……谁知道呢?!
希望这是有道理的。
关于c - Recv 返回比消息长度多的字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53326459/
#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
我是一名优秀的程序员,十分优秀!