在lib文件夹下实现了一些函数
This commit is contained in:
parent
3ae572a20a
commit
9b37061a49
3
.gitignore
vendored
3
.gitignore
vendored
@ -33,4 +33,5 @@ build/
|
||||
*.app
|
||||
|
||||
.vscode/
|
||||
.cache/
|
||||
.cache/
|
||||
.DS_Store
|
3
README
Normal file
3
README
Normal file
@ -0,0 +1,3 @@
|
||||
# UNIX Network Programming, Volume 1
|
||||
|
||||
代码在Mac OS 15.3.2 (24D81)经过测试,Windows和Linux上不保证功能都正常
|
74
lib/readline.c
Normal file
74
lib/readline.c
Normal 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
45
lib/readn.c
Normal 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
62
lib/sock_bind_wild.c
Normal 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
25
lib/sock_cmp_addr.c
Normal 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
25
lib/sock_get_port.c
Normal 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;
|
||||
}
|
@ -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
42
lib/sock_ntop_host.c
Normal 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
28
lib/sock_set_addr.c
Normal file
@ -0,0 +1,28 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <cstring>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
|
||||
/*
|
||||
* 设置sockaddr中的sin_addr和sin6_addr,addr参数是网络字节序
|
||||
*/
|
||||
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
27
lib/sock_set_port.c
Normal file
@ -0,0 +1,27 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <cstring>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
/*
|
||||
* 设置sockaddr中的port,port参数是网络字节序
|
||||
*/
|
||||
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
33
lib/sock_set_wild.c
Normal 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
62
lib/unp.h
Normal 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_addr,addr参数是网络字节序
|
||||
*/
|
||||
void
|
||||
sock_set_addr(struct sockaddr *sa, socklen_t salen, const void *addr);
|
||||
|
||||
/*
|
||||
* 设置sockaddr中的port,port参数是网络字节序
|
||||
*/
|
||||
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
39
lib/writen.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user