将C数组初始化为自定义字符

时间:2018-12-16 17:12:13

标签: c winsock2

我已经构建了Winsock2服务器。该程序的一部分具有从客户端接收数据的功能。最初,我构建的接收函数将监视传入的数据,并确定是否有任何其他数据要读取,然后再允许recv()从缓冲区中提取数据。在项目开始时,此方法运行良好,但我现在正在努力提高性能。

这是我为消除对peek的使用而编写的代码的一部分:

    unsigned char recv_buffer[4096];
    unsigned char *pComplete_buffer = malloc(sizeof(recv_buffer) * sizeof(unsigned char*));
    int offset = 0;
    int i = 0;

    ...

    for (i; i <= sizeof(recv_buffer); i++) {
        if (recv_buffer[i] == NULL) {
            break;
        }
        pComplete_buffer[offset] = recv_buffer[i];
        offset++;
    }

    ...

此代码可以很好地工作,但是问题是NULL == 0。如果客户端碰巧发送了0,则此循环将过早中断。我以为我会很聪明,将数据未初始化为0xcc并使用它来确定recv_buffer的结尾,但是似乎客户端有时也会将其作为数据的一部分发送。

问题:

是否存在可以初始化recv_buffer并可以可靠断开的字符?

如果没有,还有其他方法可以消除对peek的使用吗?

2 个答案:

答案 0 :(得分:2)

正确的解决方案是跟踪从recv_buffer开始存储的字节数。 sizeof()给出了缓冲区的TOTAL POSSIBLE大小,但是并没有告诉您实际上有多少字节包含有效数据。

recv()告诉您返回给您的字节数。将数据recv() recv_bufferrecv_buffer时,使用该返回值递增定义的变量,以指示unsigned char recv_buffer[4096]; int num_read, recv_buffer_size = 0; const int max_cbuffer_size = sizeof(recv_buffer) * sizeof(unsigned char*); unsigned char *pComplete_buffer = malloc(max_cbuffer_size); ... num_read = recv(..., recv_buffer, sizeof(recv_buffer), ...); if (num_read <= 0) { // error handling... return; } recv_buffer_size = num_read; ... int available = max_cbuffer_size - offset; int num_to_copy = min(recv_buffer_size, available); memcpy(pComplete_buffer + offset, recv_buffer, num_to_copy); offset += num_to_copy; memmove(recv_buffer, recv_buffer + num_to_copy, recv_buffer_size - num_to_copy); recv_buffer_size -= num_to_copy; ... 中的有效字节数。

例如:

Info:   Server shutdown initiated
Info:   Unregistered com.sun.enterprise.glassfish.bootstrap.osgi.EmbeddedOSGiGlassFishImpl@6014a9ba from service registry.
Info:   FileMonitoring shutdown
Info:   JMXStartupService: Stopped JMXConnectorServer: null
Info:   JMXStartupService and JMXConnectors have been shut down.
Info:   JdbcRuntimeExtension,  getAllSystemRAResourcesAndPools = [GlassFishConfigBean.org.glassfish.jdbc.config.JdbcResource, GlassFishConfigBean.org.glassfish.jdbc.config.JdbcResource, GlassFishConfigBean.org.glassfish.jdbc.config.JdbcResource, GlassFishConfigBean.org.glassfish.jdbc.config.JdbcConnectionPool, GlassFishConfigBean.org.glassfish.jdbc.config.JdbcConnectionPool, GlassFishConfigBean.org.glassfish.jdbc.config.JdbcConnectionPool]
Completed shutdown of Log manager service
Info:   Shutdown procedure finished
Completed shutdown of GlassFish runtime
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=192m; support was removed in 8.0
Listening for transport dt_socket at address: 9009
Launching GlassFish on Felix platform
Dec 18, 2018 9:32:43 AM com.sun.enterprise.glassfish.bootstrap.osgi.BundleProvisioner createBundleProvisioner
INFO: Create bundle provisioner class = class com.sun.enterprise.glassfish.bootstrap.osgi.BundleProvisioner.
Dec 18, 2018 9:32:43 AM com.sun.enterprise.glassfish.bootstrap.osgi.BundleProvisioner$DefaultCustomizer getLocations
WARNING: Skipping entry  because it is not an absolute URI.
Dec 18, 2018 9:32:43 AM com.sun.enterprise.glassfish.bootstrap.osgi.BundleProvisioner$DefaultCustomizer getLocations
WARNING: Skipping entry  because it is not an absolute URI.
Registered com.sun.enterprise.glassfish.bootstrap.osgi.EmbeddedOSGiGlassFishRuntime@1943da0 in service registry.
Found populator: com.sun.enterprise.v3.server.GFDomainXml
#!## LogManagerService.postConstruct : rootFolder=C:\Program Files\glassfish-4.1\glassfish
#!## LogManagerService.postConstruct : templateDir=C:\Program Files\glassfish-4.1\glassfish\lib\templates
#!## LogManagerService.postConstruct : src=C:\Program Files\glassfish-4.1\glassfish\lib\templates\logging.properties
#!## LogManagerService.postConstruct : dest=C:\Users\nurasahardid\AppData\Roaming\NetBeans\8.0.2\config\GF_4.1\domain1\config\logging.properties
Info:   Running GlassFish Version: GlassFish Server Open Source Edition  4.1  (build 13)
Info:   Server log file is using Formatter class: com.sun.enterprise.server.logging.ODLLogFormatter
Info:   Realm [admin-realm] of classtype [com.sun.enterprise.security.auth.realm.file.FileRealm] successfully created.
Info:   Realm [file] of classtype [com.sun.enterprise.security.auth.realm.file.FileRealm] successfully created.
Info:   Realm [certificate] of classtype [com.sun.enterprise.security.auth.realm.certificate.CertificateRealm] successfully created.
Info:   Registered org.glassfish.ha.store.adapter.cache.ShoalBackingStoreProxy for persistence-type = replicated in BackingStoreFactoryRegistry
Info:   Authorization Service has successfully initialized.
Info:   Grizzly Framework 2.3.15 started in: 31ms - bound to [/0.0.0.0:8080]
Info:   Grizzly Framework 2.3.15 started in: 0ms - bound to [/0.0.0.0:8181]
Info:   Grizzly Framework 2.3.15 started in: 0ms - bound to [/0.0.0.0:4848]
Info:   Grizzly Framework 2.3.15 started in: 15ms - bound to [/0.0.0.0:3700]
Info:   GlassFish Server Open Source Edition  4.1  (13) startup time : Felix (2,138ms), startup services(1,059ms), total(3,197ms)
Info:   Grizzly Framework 2.3.15 started in: 78ms - bound to [/0.0.0.0:7676]
Info:   Registered com.sun.enterprise.glassfish.bootstrap.osgi.EmbeddedOSGiGlassFishImpl@6014a9ba as OSGi service registration: org.apache.felix.framework.ServiceRegistrationImpl@107f4980.
Info:   JMXStartupService has started JMXConnector on JMXService URL service:jmx:rmi://10.211.55.3:8686/jndi/rmi://10.211.55.3:8686/jmxrmi
Info:   HV000001: Hibernate Validator 5.0.0.Final
Info:   Grizzly Framework 2.3.15 started in: 31ms - bound to [/0.0.0.0:8181]
Info:   Grizzly Framework 2.3.15 started in: 0ms - bound to [/0.0.0.0:8080]

答案 1 :(得分:0)

  

有没有可以初始化recv_buffer并可靠中断的字符?

不。如果对方可以随时发送任何字符,则必须检查它们。

如果您知道发件人将永远不会连续发送两个 NUL\0\0),则可以进行检查。但是有一天,发件人将决定这样做。

如果您可以更改消息结构,那么我将首先发送消息长度(以字节为单位,取决于您的协议,网络顺序为short或int)。然后,在解析该长度之后,接收器将确切知道要继续读取多长时间。 另外,如果您使用的是select,它将阻塞直到有需要阅读的内容或套接字关闭为止(主要是-阅读文档)。