Files
cKit/Foundation/c_SocketStream.c
T
2026-09-07 21:37:10 +08:00

126 lines
4.3 KiB
C

#include <c_SocketStream.h>
#if defined(_WIN32) || defined(_WIN64)
#include <winsock2.h>
#else
#include <sys/socket.h>
#include <unistd.h>
#endif
/* ================================================================================================================== */
/* [套接字输入流子类]: c_SocketInStream 内部具体化上下文 */
typedef struct {
c_InStream_t base;
c_socket_t sock;
c_Allocator_t allocator;
} c_SocketInImpl_t;
static c_err_t _SocketIn_Read(c_InStream_t* self, void* buf, c_size_t len, c_size_t* bytes_read) {
c_SocketInImpl_t* impl = (c_SocketInImpl_t*)self;
if (impl->sock == C_INVALID_SOCKET || !buf || len == 0) return C_ERR_PARAM;
/* 执行底层网络字节流套接字拦截 */
#if defined(_WIN32) || defined(_WIN64)
int n = recv(impl->sock, (char*)buf, (int)len, 0);
#else
ssize_t n = recv(impl->sock, buf, (size_t)len, 0);
#endif
if (n == 0) {
if (bytes_read) *bytes_read = 0;
return C_ERR_OUTOFBOUND; /* 对端优雅关闭连接 */
}
if (n == C_SOCKET_ERROR) {
if (bytes_read) *bytes_read = 0;
return C_ERR_FAIL; /* 网络链路异常断开 */
}
if (bytes_read) *bytes_read = (c_size_t)n;
return ( (c_size_t)n == len ) ? C_SUCCESS : C_ERR_OK; /* 部分读取或完全读取皆视为合规 */
}
static void _SocketIn_Destroy(c_InStream_t* self) {
c_SocketInImpl_t* impl = (c_SocketInImpl_t*)self;
c_Allocator_t alloc = impl->allocator;
c_Allocator_Free(&alloc, impl);
}
static const c_InStreamVtbl_t g_SocketInVtbl = { _SocketIn_Read, _SocketIn_Destroy };
c_err_t c_SocketInStream_Create(c_InStream_t** out_stream, c_socket_t sock, c_Allocator_t* allocator) {
if (!out_stream || sock == C_INVALID_SOCKET) return C_ERR_PARAM;
c_Allocator_t alloc = allocator ? *allocator : c_DefaultAllocator;
c_SocketInImpl_t* impl = (c_SocketInImpl_t*)c_Allocator_Calloc(&alloc, 1, sizeof(c_SocketInImpl_t));
if (!impl) return C_ERR_NOMEM;
impl->base.vtbl = &g_SocketInVtbl;
impl->sock = sock;
impl->allocator = alloc;
*out_stream = &impl->base;
return C_SUCCESS;
}
/* ================================================================================================================== */
/* [套接字输出流子类]: c_SocketOutStream 内部具体化上下文 */
typedef struct {
c_OutStream_t base;
c_socket_t sock;
c_Allocator_t allocator;
} c_SocketOutImpl_t;
static c_err_t _SocketOut_Write(c_OutStream_t* self, const void* buf, c_size_t len, c_size_t* bytes_written) {
c_SocketOutImpl_t* impl = (c_SocketOutImpl_t*)self;
if (impl->sock == C_INVALID_SOCKET || !buf || len == 0) return C_ERR_PARAM;
#if defined(_WIN32) || defined(_WIN64)
int n = send(impl->sock, (const char*)buf, (int)len, 0);
#else
/* MSG_NOSIGNAL 能够有效防止 Unix 系统在往断开的连接写入时触发致命的 SIGPIPE 信号崩溃进程 */
#ifdef MSG_NOSIGNAL
ssize_t n = send(impl->sock, buf, (size_t)len, MSG_NOSIGNAL);
#else
ssize_t n = send(impl->sock, buf, (size_t)len, 0);
#endif
#endif
if (n == C_SOCKET_ERROR) {
if (bytes_written) *bytes_written = 0;
return C_ERR_FAIL;
}
if (bytes_written) *bytes_written = (c_size_t)n;
return ( (c_size_t)n == len ) ? C_SUCCESS : C_ERR_FAIL;
}
static c_err_t _SocketOut_Flush(c_OutStream_t* self) {
/* TCP 套接字在操作系统内核层通常是实时刷新或通过 Nagle 算法控制,上层虚函数表在此可直接视为合规 */
(void)self;
return C_SUCCESS;
}
static void _SocketOut_Destroy(c_OutStream_t* self) {
c_SocketOutImpl_t* impl = (c_SocketOutImpl_t*)self;
c_Allocator_t alloc = impl->allocator;
c_Allocator_Free(&alloc, impl);
}
static const c_OutStreamVtbl_t g_SocketOutVtbl = { _SocketOut_Write, _SocketOut_Flush, _SocketOut_Destroy };
c_err_t c_SocketOutStream_Create(c_OutStream_t** out_stream, c_socket_t sock, c_Allocator_t* allocator) {
if (!out_stream || sock == C_INVALID_SOCKET) return C_ERR_PARAM;
c_Allocator_t alloc = allocator ? *allocator : c_DefaultAllocator;
c_SocketOutImpl_t* impl = (c_SocketOutImpl_t*)c_Allocator_Calloc(&alloc, 1, sizeof(c_SocketOutImpl_t));
if (!impl) return C_ERR_NOMEM;
impl->base.vtbl = &g_SocketOutVtbl;
impl->sock = sock;
impl->allocator = alloc;
*out_stream = &impl->base;
return C_SUCCESS;
}