v1.7.2 Release
This commit is contained in:
95
examples/07-send_size.c
Normal file
95
examples/07-send_size.c
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#define SOCK_IMPLEMENTATION
|
||||||
|
#include "sock.h"
|
||||||
|
|
||||||
|
void send_len(Sock *s, const void *buf, size_t size)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
// First send size of msg
|
||||||
|
ok = sock_send_all(s, &size, sizeof(size));
|
||||||
|
assert(ok);
|
||||||
|
|
||||||
|
// Then send msg
|
||||||
|
ok = sock_send_all(s, buf, size);
|
||||||
|
assert(ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
void server()
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
Sock *server = sock_create(SOCK_IPV4, SOCK_TCP);
|
||||||
|
assert(server != NULL);
|
||||||
|
|
||||||
|
ok = sock_bind(server, sock_addr("0.0.0.0", 6969));
|
||||||
|
assert(ok);
|
||||||
|
|
||||||
|
ok = sock_listen(server);
|
||||||
|
assert(ok);
|
||||||
|
|
||||||
|
Sock *client = sock_accept(server);
|
||||||
|
assert(client != NULL);
|
||||||
|
|
||||||
|
ssize_t n = 0;
|
||||||
|
|
||||||
|
size_t len = 0;
|
||||||
|
n = sock_recv_all(client, &len, sizeof(len));
|
||||||
|
assert(n >= 0);
|
||||||
|
|
||||||
|
char buf[len + 1];
|
||||||
|
memset(buf, 0, len + 1);
|
||||||
|
|
||||||
|
n = sock_recv_all(client, buf, len);
|
||||||
|
assert(n >= 0);
|
||||||
|
printf("%.*s\n", (int)len, buf);
|
||||||
|
|
||||||
|
const char *msg = "Hello from Server";
|
||||||
|
send_len(client, msg, strlen(msg));
|
||||||
|
|
||||||
|
sock_close(client);
|
||||||
|
sock_close(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
void client()
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
Sock *sock = sock_create(SOCK_IPV4, SOCK_TCP);
|
||||||
|
assert(sock != NULL);
|
||||||
|
|
||||||
|
ok = sock_connect(sock, sock_addr("127.0.0.1", 6969));
|
||||||
|
assert(ok);
|
||||||
|
|
||||||
|
const char *msg = "Hello from Client";
|
||||||
|
send_len(sock, msg, strlen(msg));
|
||||||
|
|
||||||
|
ssize_t n = 0;
|
||||||
|
|
||||||
|
size_t len = 0;
|
||||||
|
n = sock_recv_all(sock, &len, sizeof(len));
|
||||||
|
assert(n >= 0);
|
||||||
|
|
||||||
|
char buf[len + 1];
|
||||||
|
memset(buf, 0, len + 1);
|
||||||
|
|
||||||
|
n = sock_recv_all(sock, buf, len);
|
||||||
|
assert(n >= 0);
|
||||||
|
printf("%.*s\n", (int)len, buf);
|
||||||
|
|
||||||
|
sock_close(sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
(void) argv;
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
server();
|
||||||
|
} else {
|
||||||
|
client();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
156
sock.h
156
sock.h
@@ -4,7 +4,7 @@
|
|||||||
# @@@@@@ #
|
# @@@@@@ #
|
||||||
# @ @ #
|
# @ @ #
|
||||||
# @====@ #
|
# @====@ #
|
||||||
# @ @ sock.h - v1.7.1 #
|
# @ @ sock.h - v1.7.2 #
|
||||||
# @ @ MIT License #
|
# @ @ MIT License #
|
||||||
# @@% .@ @ #
|
# @@% .@ @ #
|
||||||
# @@ @ @ https://github.com/seajee/sock.h #
|
# @@ @ @ https://github.com/seajee/sock.h #
|
||||||
@@ -101,12 +101,22 @@
|
|||||||
// sock. On success returns the number of bytes sent. On error a negative
|
// sock. On success returns the number of bytes sent. On error a negative
|
||||||
// number shall be returned.
|
// number shall be returned.
|
||||||
//
|
//
|
||||||
|
// bool sock_send_all(Sock *sock, const void *buf, size_t size)
|
||||||
|
//
|
||||||
|
// Same as sock_send() but ensures that all of the content of buf is sent. On
|
||||||
|
// error returns false.
|
||||||
|
//
|
||||||
// ssize_t sock_recv(Sock *sock, void *buf, size_t size)
|
// ssize_t sock_recv(Sock *sock, void *buf, size_t size)
|
||||||
//
|
//
|
||||||
// Same as recv() but with socks: receives a message from sock end writes it
|
// Same as recv() but with socks: receives a message from sock end writes it
|
||||||
// into the specified buffer. On sucess returns the number of bytes received.
|
// into the specified buffer. On sucess returns the number of bytes received.
|
||||||
// On error a negative number shall be returned.
|
// On error a negative number shall be returned.
|
||||||
//
|
//
|
||||||
|
// ssize_t sock_recv_all(Sock *sock, void *buf, size_t size);
|
||||||
|
//
|
||||||
|
// Same as sock_recv() but ensures that the specified size of bytes will be
|
||||||
|
// received. On error a negative value is returned.
|
||||||
|
//
|
||||||
// ssize_t sock_sendto(Sock *sock, const void *buf, size_t size, SockAddr addr)
|
// ssize_t sock_sendto(Sock *sock, const void *buf, size_t size, SockAddr addr)
|
||||||
//
|
//
|
||||||
// Same as sendto() but with socks: the return value works the same way as
|
// Same as sendto() but with socks: the return value works the same way as
|
||||||
@@ -246,9 +256,11 @@ bool sock_connect(Sock *sock, SockAddr addr);
|
|||||||
|
|
||||||
// Send data through a socket
|
// Send data through a socket
|
||||||
ssize_t sock_send(Sock *sock, const void *buf, size_t size);
|
ssize_t sock_send(Sock *sock, const void *buf, size_t size);
|
||||||
|
bool sock_send_all(Sock *sock, const void *buf, size_t size);
|
||||||
|
|
||||||
// Receive data from a socket
|
// Receive data from a socket
|
||||||
ssize_t sock_recv(Sock *sock, void *buf, size_t size);
|
ssize_t sock_recv(Sock *sock, void *buf, size_t size);
|
||||||
|
ssize_t sock_recv_all(Sock *sock, void *buf, size_t size);
|
||||||
|
|
||||||
// Send data through a socket in connectionless mode
|
// Send data through a socket in connectionless mode
|
||||||
ssize_t sock_sendto(Sock *sock, const void *buf, size_t size, SockAddr addr);
|
ssize_t sock_sendto(Sock *sock, const void *buf, size_t size, SockAddr addr);
|
||||||
@@ -465,6 +477,11 @@ Sock *sock_accept(Sock *sock)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sock->type != SOCK_TCP) {
|
||||||
|
sock->last_errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
Sock *res = (Sock*)malloc(sizeof(*res));
|
Sock *res = (Sock*)malloc(sizeof(*res));
|
||||||
if (res == NULL) {
|
if (res == NULL) {
|
||||||
sock->last_errno = errno;
|
sock->last_errno = errno;
|
||||||
@@ -494,6 +511,11 @@ bool sock_async_accept(Sock *sock, SockThreadCallback fn, void *user_data)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sock->type != SOCK_TCP) {
|
||||||
|
sock->last_errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
Sock *client = sock_accept(sock);
|
Sock *client = sock_accept(sock);
|
||||||
if (client == NULL) {
|
if (client == NULL) {
|
||||||
return false;
|
return false;
|
||||||
@@ -530,6 +552,11 @@ bool sock_connect(Sock *sock, SockAddr addr)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sock->type != SOCK_TCP) {
|
||||||
|
sock->last_errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (connect(sock->fd, &addr.sockaddr, addr.len) < 0) {
|
if (connect(sock->fd, &addr.sockaddr, addr.len) < 0) {
|
||||||
sock->last_errno = errno;
|
sock->last_errno = errno;
|
||||||
return false;
|
return false;
|
||||||
@@ -542,34 +569,131 @@ bool sock_connect(Sock *sock, SockAddr addr)
|
|||||||
|
|
||||||
ssize_t sock_send(Sock *sock, const void *buf, size_t size)
|
ssize_t sock_send(Sock *sock, const void *buf, size_t size)
|
||||||
{
|
{
|
||||||
if (sock == NULL || buf == NULL) {
|
if (sock == NULL || buf == NULL || sock->type != SOCK_TCP) {
|
||||||
|
if (sock != NULL) {
|
||||||
|
sock->last_errno = EINVAL;
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return send(sock->fd, buf, size, 0);
|
while (true) {
|
||||||
|
ssize_t n = send(sock->fd, buf, size, 0);
|
||||||
|
if (n < 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sock->last_errno = errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sock_send_all(Sock *sock, const void *buf, size_t size)
|
||||||
|
{
|
||||||
|
if (sock == NULL || buf == NULL || sock->type != SOCK_TCP) {
|
||||||
|
if (sock != NULL) {
|
||||||
|
sock->last_errno = EINVAL;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t *ptr = (uint8_t*)buf;
|
||||||
|
size_t remaining = size;
|
||||||
|
|
||||||
|
while (remaining > 0) {
|
||||||
|
ssize_t n = sock_send(sock, ptr, remaining);
|
||||||
|
if (n < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr += n;
|
||||||
|
remaining -= n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t sock_recv(Sock *sock, void *buf, size_t size)
|
ssize_t sock_recv(Sock *sock, void *buf, size_t size)
|
||||||
{
|
{
|
||||||
if (sock == NULL || buf == NULL) {
|
if (sock == NULL || buf == NULL || sock->type != SOCK_TCP) {
|
||||||
|
if (sock != NULL) {
|
||||||
|
sock->last_errno = EINVAL;
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return recv(sock->fd, buf, size, 0);
|
while (true) {
|
||||||
|
ssize_t n = recv(sock->fd, buf, size, 0);
|
||||||
|
if (n < 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sock->last_errno = errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t sock_recv_all(Sock *sock, void *buf, size_t size)
|
||||||
|
{
|
||||||
|
if (sock == NULL || buf == NULL || sock->type != SOCK_TCP) {
|
||||||
|
if (sock != NULL) {
|
||||||
|
sock->last_errno = EINVAL;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *ptr = (uint8_t*)buf;
|
||||||
|
size_t remaining = size;
|
||||||
|
ssize_t total = 0;
|
||||||
|
|
||||||
|
while (remaining > 0) {
|
||||||
|
ssize_t n = sock_recv(sock, ptr, remaining);
|
||||||
|
if (n < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (n == 0) {
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
ptr += n;
|
||||||
|
remaining -= n;
|
||||||
|
total += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t sock_sendto(Sock *sock, const void *buf, size_t size, SockAddr addr)
|
ssize_t sock_sendto(Sock *sock, const void *buf, size_t size, SockAddr addr)
|
||||||
{
|
{
|
||||||
if (sock == NULL || buf == NULL) {
|
if (sock == NULL || buf == NULL || sock->type != SOCK_UDP) {
|
||||||
|
if (sock != NULL) {
|
||||||
|
sock->last_errno = EINVAL;
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sendto(sock->fd, buf, size, 0, &addr.sockaddr, addr.len);
|
while (true) {
|
||||||
|
ssize_t n = sendto(sock->fd, buf, size, 0, &addr.sockaddr, addr.len);
|
||||||
|
if (n < 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sock->last_errno = errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t sock_recvfrom(Sock *sock, void *buf, size_t size, SockAddr *addr)
|
ssize_t sock_recvfrom(Sock *sock, void *buf, size_t size, SockAddr *addr)
|
||||||
{
|
{
|
||||||
if (sock == NULL || buf == NULL) {
|
if (sock == NULL || buf == NULL || sock->type != SOCK_UDP) {
|
||||||
|
if (sock != NULL) {
|
||||||
|
sock->last_errno = EINVAL;
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,9 +708,17 @@ ssize_t sock_recvfrom(Sock *sock, void *buf, size_t size, SockAddr *addr)
|
|||||||
len_ptr = &sa_len;
|
len_ptr = &sa_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t res = recvfrom(sock->fd, buf, size, 0, sa, len_ptr);
|
ssize_t res = 0;
|
||||||
if (res < 0 || addr == NULL) {
|
while (true) {
|
||||||
return res;
|
res = recvfrom(sock->fd, buf, size, 0, sa, len_ptr);
|
||||||
|
if (res < 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sock->last_errno = errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr != NULL) {
|
if (addr != NULL) {
|
||||||
@@ -678,6 +810,8 @@ void sock__convert_addr(SockAddr *addr)
|
|||||||
/*
|
/*
|
||||||
Revision history:
|
Revision history:
|
||||||
|
|
||||||
|
1.7.2 (2025-09-17) New functions sock_recv_all() and sock_send_all();
|
||||||
|
Improved error reporting.
|
||||||
1.7.1 (2025-09-07) Pass NULL to getaddrinfo if port is 0 in sock_dns()
|
1.7.1 (2025-09-07) Pass NULL to getaddrinfo if port is 0 in sock_dns()
|
||||||
1.7.0 (2025-09-06) Header now includes documentation; New sock_dns()
|
1.7.0 (2025-09-06) Header now includes documentation; New sock_dns()
|
||||||
function; major improvements and refactoring
|
function; major improvements and refactoring
|
||||||
|
|||||||
Reference in New Issue
Block a user