假设本地linux主机上的TCP套接字与远程主机处于连接状态.本地主机正在使用epoll_wait通知远程主机的套接字上的事件.
如果远程主机要打电话:
shutdown(s,SHUT_WR);
Run Code Online (Sandbox Code Playgroud)
在其连接的套接字上,表明它已完成传输,epoll_wait将在本地主机上为其套接字返回什么事件?
我假设总是会返回EPOLLIN并且后续的recv调用将返回0以指示远程端已完成传输.
EPOLLHUP或EPOLLRDHUP怎么样?(这两个事件有什么区别)?
甚至EPOLLERR?
如果远程主机呼叫"关闭"而不是"关闭",上述任何一个的答案是否会改变?
将普通的旧数据类型和对象作为成员的普通结构(或类).请注意,没有定义默认构造函数.
struct Foo
{
int x;
int y;
double z;
string str;
};
Run Code Online (Sandbox Code Playgroud)
现在,如果我在堆栈上声明一个实例f并尝试打印其内容:
{
Foo f;
std::cout << f.x << " " << f.y << " " << f.z << f.str << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
结果是为x,y和z打印的垃圾数据.并且字符串默认初始化为空. 正如所料.
如果我创建一个shared_ptr<Foo>使用make_shared和打印的实例:
{
shared_ptr<Foo> spFoo = make_shared<Foo>();
cout << spFoo->x << " " << spFoo->y << " " << spFoo->z << spFoo->str << endl;
}
Run Code Online (Sandbox Code Playgroud)
然后,x,y和z都是0.这使得它似乎shared_ptr在构造对象实例后对每个成员执行默认初始化(零init).至少这是我用Visual Studio的编译器观察到的.
这是C++的标准吗?或者是否有必要={}在实例化后使用显式构造函数或显式语句来保证所有编译器的零init行为?
想象一个由32位,16位和8位成员值组成的结构.成员值的排序使得每个成员都在其自然边界上.
struct Foo
{
uint32_t a;
uint16_t b;
uint8_t c;
uint8_t d;
uint32_t e;
};
Run Code Online (Sandbox Code Playgroud)
为Visual C++ 记录了成员对齐和填充规则.VC++上的sizeof(Foo)上面的结构可以预测为"12".
现在,我很确定规则是不应该对填充和对齐做出任何假设,但在实践中,其他操作系统上的其他编译器是否也做出类似的保证?
如果没有,GCC上是否有相同的"#pragma pack(1)"?
我有很长一段时间以前在某些环境中工作的代码.我很确定它是一台FreeBSD机器所以我得到了FreeBSD 8.3而我正在尝试制作这个文件,但是它没有用.
当我尝试编译它时,它抱怨:
f.c: In function 'tcp'>
f.c:24: error: storage size of 'socket_stru' isn't known
f.c:29: error: 'IPPROTO_TCP' undeclared (first use in this function)
...
Run Code Online (Sandbox Code Playgroud)
我一直在环顾四周,我看到这些都是在sys/socket.h文件中指定的.这是我的实际文件:
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <unistd.h>
#include "f.h"
int tcp4 (in_addr_t ip, int port, int qsize )
{
struct sockaddr_in socket_stru; // line 24
socket_stru.sin_family = AF_INET;
socket_stru.sin_port = htons(port);
socket_stru.sin_addr.s_addr = ip;
int actual_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); // line 29
...
Run Code Online (Sandbox Code Playgroud)
我觉得我的代码不知道"不读取"sys/socket.h文件所以它不知道socket_stru和IPPROTO_TCP,但我真的迷路了.
有任何想法吗?
考虑以下两个几乎相同的方法调用.记下在两者上声明和分配字节数组的方式.
void Method1()
{
byte [] bytearray = new byte[16];
/* some code */
}
void Method2()
{
byte [] bytearray = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
/* some code */
}
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,假设当Method1和Method2返回时,"bytearray"是垃圾收集的候选者,因为操作bytearray变量的代码都不会持有超出方法本身末尾的引用.
Method2是否通过避免调用"new"来更快地(或不同地)运行?或者上述两种实现是否相同?在任何一种情况下,Java编译器或运行时都可以进行优化以避免为这个短暂的临时缓冲区命中内存分配器的开销吗?
在我的Android音乐流应用程序中,下面的代码路径有助于根据ConnectivityManager类实例返回的值在高比特率流与低比特率之间进行决策.
我试图理解为什么ConnectivityManager.isActiveNetworkMetered()将返回"true",这显然我在本地Wifi网络上.采用以下Android/Java代码:
boolean isMetered = false;
boolean isWifi = false;
boolean isEthernet = false;
boolean isRoaming = false;
boolean isConnected = false;
NetworkInfo netinfo = connManager.getActiveNetworkInfo();
if (netinfo != null)
{
isWifi = (netinfo.getType() == ConnectivityManager.TYPE_WIFI);
isEthernet = (netinfo.getType() == ConnectivityManager.TYPE_ETHERNET);
isRoaming = netinfo.isRoaming();
isConnected = netinfo.isConnected();
Log.d(TAG, "active network type = " + netinfo.getTypeName());
Log.d(TAG, "active network subtype = " + netinfo.getSubtypeName());
Log.d(TAG, "isConnected = " + isConnected);
Log.d(TAG, "isWifi = " + isWifi);
Log.d(TAG, "isEthernet = " + …Run Code Online (Sandbox Code Playgroud) 我已经阅读了C10K文档以及关于扩展套接字服务器的许多相关文章.所有道路都指向以下内容:
避免"每个连接的线程"的经典错误.
优先选择epoll.
同样,unix中的遗留异步io机制可能很难使用.
我的简单TCP服务器只是在专用端口上侦听侦听套接字上的客户端连接.收到新连接后,解析请求,然后发回响应.然后优雅地关闭套接字.
我想我可以很好地处理如何使用epoll在单个线程上扩展它.只有一个循环调用epoll_wait作为listen套接字以及现有的客户端连接.返回后,代码将处理新的创建新客户端连接以及管理现有连接的状态,具体取决于刚刚发出信号的套接字.也许还有一些逻辑来管理连接超时,正常关闭套接字以及为每个连接分配有效的资源.看起来很简单.
但是如果我想扩展它以利用多个线程和多个cpu内核呢? 想到的核心理念是:
一个专用线程,用于侦听TCP侦听套接字上的传入连接.然后是一组N个线程(或线程池)来处理所有活动的并发客户端连接.然后发明一些线程安全的方法,其中listen线程将"新的连接(套接字)""分派"到一个可用的工作线程.(Windows中的ala IOCP).工作线程将在其处理的所有连接上使用epoll循环来执行单线程方法将执行的操作.
我是在正确的轨道上吗?或者是否有一个标准的设计模式用于在多个线程上使用epoll执行TCP服务器?
关于监听线程如何将新连接分派给线程池的建议?
关于htonl和ntohl.何时将这两行代码中的任何一行评估为false.
htonl(x) == ntohl(x);
htonl(ntohl(x)) == htonl(htonl(x));
Run Code Online (Sandbox Code Playgroud)
换句话说,这两个操作何时在同一台机器上不相同?我能想到的唯一场景是一台机器,它不能用于表示整数的2的补码.
原因主要是历史,编码清晰度还是其他原因?
今天是否存在任何现代架构或环境,在这两个方向上,这些在同一台机器上的网络字节顺序转换是不同的代码?
我试图在C++中创建一个位集矢量.为此,我尝试了下面的代码片段中显示的尝试:
vector<bitset<8>> bvc;
while (true) {
bitset<8> bstemp( (long) xtemp );
if (bstemp.count == y1) {
bvc.push_back(bstemp);
}
if ( xtemp == 0) {
break;
}
xtemp = (xtemp-1) & ntemp;
}
Run Code Online (Sandbox Code Playgroud)
当我尝试编译程序时,我得到的错误是读取bvc未在范围中声明的内容.它进一步告诉模板参数1和2无效.(第1行).另外,在包含的行中bvc.push_back(bstemp),我收到的错误是读取成员函数的无效使用.
我在日志助手函数中使用strerror_r.如手册页所述,此功能有两个版本.POSIX版本返回一个int.GNU版本返回一个字符串(char*).
因此,为了使我的C++代码更具可移植性,我有一段类似于此的代码:
char buffer[1000];
int size = 1000;
int result = 0;
char* msg = buffer;
buffer[0] = '\0';
#ifdef _GNU_SOURCE
msg = strerror_r(err, buffer, size);
#else
result = strerror_r(err, buffer, size);
if (result != 0)
{
sprintf(buffer, "unknown error: %d", err);
}
#endif
LogToFile(msg);
Run Code Online (Sandbox Code Playgroud)
在上面的代码块中,它将使用任何一个版本strerror_r取决于是否存在_GNU_SOURCE,这总是由g ++设置,因为libstdc ++需要它.在Mac和Unix的其他版本中,它将使用POSIX版本.
现在这个代码已经很长时间以来一直很好用到今天.一个用户试图在Alpine Linux上编译我的代码,并在今天使用该行报告此编译器错误strerror_r
main.cpp:16:21 error: invalid conversion from 'int' to 'char*' [-fpermissive]
Run Code Online (Sandbox Code Playgroud)
哪个映射到此行:
#ifdef _GNU_SOURCE
msg = strerror_r(err, buffer, size);
Run Code Online (Sandbox Code Playgroud)
/usr/include/string.h在这个平台上达到顶峰揭示了以下内容:
#if defined(_POSIX_SOURCE) …Run Code Online (Sandbox Code Playgroud)