在lib文件夹下实现了一些函数

This commit is contained in:
Gary Gan 2025-04-18 21:57:19 +08:00
parent 3ae572a20a
commit 9b37061a49
14 changed files with 487 additions and 2 deletions

3
.gitignore vendored
View File

@ -33,4 +33,5 @@ build/
*.app
.vscode/
.cache/
.cache/
.DS_Store

3
README Normal file
View File

@ -0,0 +1,3 @@
# UNIX Network Programming, Volume 1
代码在Mac OS 15.3.2 (24D81)经过测试Windows和Linux上不保证功能都正常

74
lib/readline.c Normal file
View File

@ -0,0 +1,74 @@
#include "unp.h"
#include <cerrno>
#include <cstddef>
#include <cstdio>
#include <iostream>
#include <unistd.h>
static int read_cnt;
static char *read_ptr;
static char read_buff[MAXLINE];
static ssize_t
my_read(int fd, char *ptr)
{
if (read_cnt <= 0) {
again:
if ( (read_cnt = read(fd, read_buff, sizeof(read_buff))) < 0) {
if (errno == EINTR)
goto again;
else if (read_cnt == 0)
return 0;
read_ptr = read_buff;
}
}
read_cnt--;
*ptr = *read_ptr++;
return 1;
}
ssize_t
readline(int fd, void *vptr, size_t maxlen)
{
ssize_t n, returnvalue;
char c, *ptr;
ptr = (char *) vptr;
for (n = 1; n < maxlen; n++) {
if ( (returnvalue = my_read(fd, &c)) == 1) {
*ptr++ = c;
if (c == '\n')
break;
else if (returnvalue == 0) {
*ptr = 0;
return (n - 1); // EOF, n - 1 bytes were read
} else {
return -1;
}
}
}
*ptr = 0;
return n;
}
ssize_t
readlinebuf(void **vptrptr)
{
if (read_cnt)
*vptrptr = read_ptr;
return read_cnt;
}
/*
*
*/
ssize_t
Readline(int fd, void *ptr, size_t maxlen)
{
ssize_t n;
if ( (n = readline(fd, ptr, maxlen)) < 0)
std::cerr << "readline error" << std::endl;
return n;
}

45
lib/readn.c Normal file
View File

@ -0,0 +1,45 @@
#include <cerrno>
#include <cstddef>
#include <cstdio>
#include <iostream>
#include <unistd.h>
ssize_t /* Read "n" bytes from a descriptor. */
readn(int fd, void *vptr, size_t n)
{
size_t nleft;
ssize_t nread;
char *ptr;
ptr = (char *) vptr;
nleft = n;
while (nleft > 0) {
if ( (nread = read(fd, ptr, nleft)) < 0) {
if (errno == EINTR)
nread = 0; /* and call read() again */
else
return(-1);
} else if (nread == 0)
break; /* EOF */
nleft -= nread;
ptr += nread;
}
return(n - nleft); /* return >= 0 */
}
/* end readn */
/*
* n个字节
*/
ssize_t
Readn(int fd, void *ptr, size_t nbytes)
{
ssize_t n;
if ( (n = readn(fd, ptr, nbytes)) < 0)
std::cerr << "readn error" << std::endl;
return(n);
}

62
lib/sock_bind_wild.c Normal file
View File

@ -0,0 +1,62 @@
#include <cstring>
#include <iostream>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
// 将socket随机绑定到一个端口
// 返回端口的值
int
sock_bind_wild(int sockfd, int family)
{
socklen_t len;
switch (family) {
case AF_INET: {
struct sockaddr_in sin;
bzero(&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(0); // 随机端口
if (bind(sockfd, (struct sockaddr *) &sin, sizeof(sin)) < 0)
return -1;
// 更新sin想内核获取具体的sockaddr_in信息
len = sizeof(sin);
if (getsockname(sockfd, (struct sockaddr *) &sin, &len) < 0)
return -1;
return sin.sin_port;
}
case AF_INET6: {
struct sockaddr_in6 sin6;
bzero(&sin6, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_addr = IN6ADDR_ANY_INIT;
sin6.sin6_port = htons(0); // 随机端口
if (bind(sockfd, (struct sockaddr *) &sin6, sizeof(sin6)) < 0)
return -1;
// 更新sin想内核获取具体的sockaddr_in信息
len = sizeof(sin6);
if (getsockname(sockfd, (struct sockaddr *) &sin6, &len) < 0)
return -1;
return sin6.sin6_port;
}
}
// end switch
return -1;
}
int
Sock_bind_wild(int sockfd, int family)
{
int port;
if ( (port = sock_bind_wild(sockfd, family)) < 0)
std::cerr << "sock_bind_wild error" << std::endl;
return port;
}

25
lib/sock_cmp_addr.c Normal file
View File

@ -0,0 +1,25 @@
#include <cstring>
#include <netinet/in.h>
#include <sys/socket.h>
/*
* 0
*/
int
sock_cmp_addr(const struct sockaddr *sa1, const struct sockaddr *sa2, socklen_t salen)
{
if (sa1->sa_family != sa2->sa_family)
return -1;
switch (sa1->sa_family) {
case AF_INET: {
return (memcmp( &((struct sockaddr_in *)sa1)->sin_addr, &((struct sockaddr_in *)sa2)->sin_addr, sizeof(in_addr)));
}
case AF_INET6: {
return (memcmp( &((struct sockaddr_in6 *)sa1)->sin6_addr, &((struct sockaddr_in6 *)sa2)->sin6_addr, sizeof(in6_addr)));
}
}
// end switch
return -1;
}

25
lib/sock_get_port.c Normal file
View File

@ -0,0 +1,25 @@
#include <netinet/in.h>
#include <sys/socket.h>
/*
* sockaddr中的port
*/
int
sock_get_port(const struct sockaddr *sa, socklen_t salen)
{
switch (sa->sa_family) {
case AF_INET: {
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
// sin_port is 16bit size
return(sin->sin_port);
}
case AF_INET6: {
struct sockaddr_in6 *sin = (struct sockaddr_in6 *) sa;
// sin_port is 16bit size
return(sin->sin6_port);
}
}
// end switch
return -1;
}

View File

@ -3,6 +3,8 @@
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <iostream>
char *
sock_ntop(const struct sockaddr *sa, socklen_t salen)
@ -37,9 +39,26 @@ sock_ntop(const struct sockaddr *sa, socklen_t salen)
// 排除'['
return str + 1;
}
default:
snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d", sa->sa_family, salen);
return str;
}
return NULL;
}
// 数字类型的sockaddr地址端口转换成字符串类型的sockaddr
// 返回字符串
char *
Sock_ntop(const struct sockaddr *sa, socklen_t salen)
{
char *ptr;
if ( (ptr = sock_ntop(sa, salen)) == NULL)
std::cerr << "sock_ntop error" << std::endl;
return ptr;
}

42
lib/sock_ntop_host.c Normal file
View File

@ -0,0 +1,42 @@
#include <cstddef>
#include <iostream>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
char *
sock_ntop_host(const sockaddr *sa, socklen_t salen)
{
static char str[128]; // Unix domain is largest
switch (sa->sa_family) {
case AF_INET: {
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL)
return NULL;
return str;
}
case AF_INET6: {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
if (inet_ntop(AF_INET, &sin6->sin6_addr, str, sizeof(str)) == NULL)
return NULL;
return str;
}
}
// end switch
return NULL;
}
/*
*
*/
char *
Sock_ntop_host(const struct sockaddr *sa, socklen_t salen)
{
char *ptr;
if( (ptr = sock_ntop_host(sa, salen)) == NULL)
std::cerr << "sock_ntop_host" << std::endl;
return ptr;
}

28
lib/sock_set_addr.c Normal file
View File

@ -0,0 +1,28 @@
#include <arpa/inet.h>
#include <cstring>
#include <netinet/in.h>
#include <sys/socket.h>
/*
* sockaddr中的sin_addr和sin6_addraddr参数是网络字节序
*/
void
sock_set_addr(struct sockaddr *sa, socklen_t salen, const void *addr)
{
switch (sa->sa_family) {
case AF_INET: {
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
memcpy(&sin->sin_addr, addr, sizeof(in_addr));
return;
}
case AF_INET6: {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
memcpy(&sin6->sin6_addr, addr, sizeof(in_addr));
return;
}
}
// end switch
}

27
lib/sock_set_port.c Normal file
View File

@ -0,0 +1,27 @@
#include <arpa/inet.h>
#include <cstring>
#include <netinet/in.h>
#include <sys/socket.h>
/*
* sockaddr中的portport参数是网络字节序
*/
void
sock_set_port(struct sockaddr *sa, socklen_t salen, int port)
{
switch (sa->sa_family) {
case AF_INET: {
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
sin->sin_port = port;
return;
}
case AF_INET6: {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
sin6->sin6_port = port;
return;
}
}
return;
}

33
lib/sock_set_wild.c Normal file
View File

@ -0,0 +1,33 @@
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "unp.h"
/*
* sa中的address设置为ANY
*/
void
sock_set_wild(struct sockaddr *sa, socklen_t salen)
{
const void *wildptr;
switch (sa->sa_family) {
case AF_INET: {
static struct in_addr in4addr_any;
in4addr_any.s_addr = htonl(INADDR_ANY);
wildptr = &in4addr_any;
break;
}
case AF_INET6: {
wildptr = &in6addr_any;
break;
}
default:
return;
}
// end switch
sock_set_addr(sa, salen, wildptr);
return;
}

62
lib/unp.h Normal file
View File

@ -0,0 +1,62 @@
#pragma once
#include <arpa/inet.h>
#define MAXLINE 4096
// 将socket随机绑定到一个端口
// 返回端口的值
int
sock_bind_wild(int sockfd, int family);
/*
* 0
*/
int
sock_cmp_addr(const struct sockaddr *sa1, const struct sockaddr *sa2, socklen_t salen);
/*
* sockaddr中的port
*/
int
sock_get_port(const struct sockaddr *sa, socklen_t salen);
/*
*
*/
char *
Sock_ntop_host(const struct sockaddr *sa, socklen_t salen);
// 数字类型的sockaddr地址端口转换成字符串类型的sockaddr
// 返回字符串
char *
Sock_ntop(const struct sockaddr *sa, socklen_t salen);
/*
* sockaddr中的sin_addr和sin6_addraddr参数是网络字节序
*/
void
sock_set_addr(struct sockaddr *sa, socklen_t salen, const void *addr);
/*
* sockaddr中的portport参数是网络字节序
*/
void
sock_set_port(struct sockaddr *sa, socklen_t salen, int port);
/*
*
*/
ssize_t
Readline(int fd, void *ptr, size_t maxlen);
/*
* n个字节
*/
void
Writen(int fd, void *ptr, size_t nbytes);
/*
* n个字节
*/
ssize_t
Readn(int fd, void *ptr, size_t nbytes);

39
lib/writen.c Normal file
View File

@ -0,0 +1,39 @@
#include <cerrno>
#include <cstddef>
#include <cstdio>
#include <iostream>
#include <unistd.h>
ssize_t
writen(int fd, const void *vptr, size_t n)
{
size_t nleft;
ssize_t nwritten;
const char *ptr;
ptr = (const char *) vptr;
nleft = n;
while (nleft > 0) {
if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
if (nwritten < 0 && errno == EINTR)
nwritten = 0; // and call write() again
else
return -1;
}
nleft -= nwritten;
ptr += nwritten;
}
return n;
}
/*
* n个字节
*/
void
Writen(int fd, void *ptr, size_t nbytes)
{
if (writen(fd, ptr, nbytes) != nbytes)
std::cerr << "writen error" << std::endl;
}