diff --git a/5/5-1byteorder.cpp b/5/5-1byteorder.cpp index 549655d..1ccfebf 100644 --- a/5/5-1byteorder.cpp +++ b/5/5-1byteorder.cpp @@ -1,22 +1,16 @@ #include -void byteorder() -{ - union - { - short value; - char union_bytes[ sizeof( short ) ]; - } test; - test.value = 0x0102; - if ( ( test.union_bytes[ 0 ] == 1 ) && ( test.union_bytes[ 1 ] == 2 ) ) - { - printf( "big endian\n" ); - } - else if ( ( test.union_bytes[ 0 ] == 2 ) && ( test.union_bytes[ 1 ] == 1 ) ) - { - printf( "little endian\n" ); - } - else - { - printf( "unknown...\n" ); - } + +void byteorder() { + union { + short value; + char union_bytes[sizeof(short)]; + } test; + test.value = 0x0102; + if ((test.union_bytes[0] == 1) && (test.union_bytes[1] == 2)) { + printf("big endian\n"); + } else if ((test.union_bytes[0] == 2) && (test.union_bytes[1] == 1)) { + printf("little endian\n"); + } else { + printf("unknown...\n"); + } } \ No newline at end of file diff --git a/5/5-3testlisten.cpp b/5/5-3testlisten.cpp index 7196c8b..e88be3e 100644 --- a/5/5-3testlisten.cpp +++ b/5/5-3testlisten.cpp @@ -7,46 +7,66 @@ #include #include #include +#include + +/** + * 执行: + * step 1: ./5-3testlisten 127.0.0.1 12345 5 // 三个参数:ip,端口号,backlog(backlog参数表示等待连接的最大数量) + * + * step 2: telnet 127.0.0.1 12345 // 使用 telnet 链接 ip,端口,重复5次以上 + * + * step 3: netstat -nt | grep 12345 查看链接情况 + * + * 结果: + * 观察到前5个建立的链接状态为 ESTABLISHED,超过5个的部分的链接状态为 SYN_SENT,随后超时 + */ static bool stop = false; -static void handle_term( int sig ) -{ + +static void handle_term(int sig) { stop = true; } -int main( int argc, char* argv[] ) -{ - signal( SIGTERM, handle_term ); +int main(int argc, char *argv[]) { + signal(SIGTERM, handle_term); - if( argc <= 3 ) - { - printf( "usage: %s ip_address port_number backlog\n", basename( argv[0] ) ); + // 参数需要大于等于三个 + if (argc <= 3) { + printf("usage: %s ip_address port_number backlog\n", basename(argv[0])); return 1; } - const char* ip = argv[1]; - int port = atoi( argv[2] ); - int backlog = atoi( argv[3] ); - int sock = socket( PF_INET, SOCK_STREAM, 0 ); - assert( sock>= 0 ); + const char *ip = argv[1]; + int port = atoi(argv[2]); + int backlog = atoi(argv[3]); + + // 创建 socket,PF_INET 表示 IPv4 地址族,SOCK_STREAM 表示使用TCP协议 + int sock = socket(PF_INET, SOCK_STREAM, 0); + assert(sock>= 0); struct sockaddr_in address; - bzero( &address, sizeof( address ) ); + // bzero() 是一个函数,用于将一块内存区域中的内容清零 + // 需要注意的是,bzero() 函数在一些新的 C 标准中已经被标记为不推荐使用,可以考虑使用 memset() 函数来达到相同的效果 + bzero(&address, sizeof(address)); + + // AF_INET 表示 IPv4 地址族 address.sin_family = AF_INET; - inet_pton( AF_INET, ip, &address.sin_addr ); - address.sin_port = htons( port ); + // 将字符串类型的 IP 地址 ip 转换为二进制格式,并将结果存储在 address.sin_addr 字段中 + inet_pton(AF_INET, ip, &address.sin_addr); + address.sin_port = htons(port); - int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) ); - assert( ret != -1 ); + // 绑定套接字和地址 + int ret = bind(sock, (struct sockaddr *) &address, sizeof(address)); + assert(ret != -1); - ret = listen( sock, backlog ); - assert( ret != -1 ); + // 设置套接字为监听状态,backlog 参数表示等待连接的最大数量 + ret = listen(sock, backlog); + assert(ret != -1); - while ( ! stop ) - { - sleep( 1 ); + while (!stop) { + sleep(1); } - close( sock ); + close(sock); return 0; } diff --git a/5/5-5testaccept.cpp b/5/5-5testaccept.cpp index a2b95b0..cd11d69 100644 --- a/5/5-5testaccept.cpp +++ b/5/5-5testaccept.cpp @@ -7,48 +7,63 @@ #include #include #include +#include -int main( int argc, char* argv[] ) -{ - if( argc <= 2 ) - { - printf( "usage: %s ip_address port_number\n", basename( argv[0] ) ); +/** + * @param sockfd 需要监听的服务器套接字描述符 + * @param addr struct sockaddr 类型的指针,用于存储连接的客户端地址信息的指针 + * @param addrlen 一个指向整数的指针,指示addr 缓冲区的长度 + * @return 接受来自客户端的 socket,返回值唯一标识被接受的链接 + * + * int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); + * + * 在 sleep 的 30 秒之中,打开并关闭 telnet,accept 依然正常返回; + * + * accept 只是从监听队列中取出连接,而不论连接处于何种状态(如 ESTABLISHED 状态和 CLOSE_WAIT 状态),更不关心任何网络状况的变化。 + */ + +int main(int argc, char *argv[]) { + if (argc <= 2) { + printf("usage: %s ip_address port_number\n", basename(argv[0])); return 1; } - const char* ip = argv[1]; - int port = atoi( argv[2] ); + const char *ip = argv[1]; + int port = atoi(argv[2]); struct sockaddr_in address; - bzero( &address, sizeof( address ) ); + bzero(&address, sizeof(address)); address.sin_family = AF_INET; - inet_pton( AF_INET, ip, &address.sin_addr ); - address.sin_port = htons( port ); + inet_pton(AF_INET, ip, &address.sin_addr); + address.sin_port = htons(port); + + // 创建服务端 socket + int sock = socket(PF_INET, SOCK_STREAM, 0); + assert(sock>= 0); - int sock = socket( PF_INET, SOCK_STREAM, 0 ); - assert( sock>= 0 ); + int ret = bind(sock, (struct sockaddr *) &address, sizeof(address)); + assert(ret != -1); - int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) ); - assert( ret != -1 ); + ret = listen(sock, 5); + assert(ret != -1); - ret = listen( sock, 5 ); - assert( ret != -1 ); + sleep(30); struct sockaddr_in client; - socklen_t client_addrlength = sizeof( client ); - int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength ); - if ( connfd < 0 ) - { - printf( "errno is: %d\n", errno ); - } - else - { - char remote[INET_ADDRSTRLEN ]; - printf( "connected with ip: %s and port: %d\n", - inet_ntop( AF_INET, &client.sin_addr, remote, INET_ADDRSTRLEN ), ntohs( client.sin_port ) ); - close( connfd ); + socklen_t client_addrlength = sizeof(client); + // 接受来自客户端的 socket,返回值唯一标识被接受的链接 + int connfd = accept(sock, (struct sockaddr *) &client, &client_addrlength); + if (connfd < 0) { + printf("errno is: %d\n", errno); + } else { + // INET_ADDRSTRLEN 宏定义,用于表示一个 IPv4 地址的字符串表示的最大长度 + // 该宏的值通常是 16,因为最长的 IPv4 地址("255.255.255.255")有 15 个字符,加上结尾的空字符0,円总共是 16 个字符。 + char remote[INET_ADDRSTRLEN]; + printf("connected with ip: %s and port: %d\n", + inet_ntop(AF_INET, &client.sin_addr, remote, INET_ADDRSTRLEN), ntohs(client.sin_port)); + close(connfd); } - close( sock ); + close(sock); return 0; } diff --git a/5/5-6oobsend.cpp b/5/5-6oobsend.cpp index 70fa13e..ed99244 100644 --- a/5/5-6oobsend.cpp +++ b/5/5-6oobsend.cpp @@ -6,39 +6,44 @@ #include #include #include +#include -int main( int argc, char* argv[] ) -{ - if( argc <= 2 ) - { - printf( "usage: %s ip_address port_number\n", basename( argv[0] ) ); + +/** + * ssize_t send(int sockfd, const void *buf, size_t len, int flags); + * + * 启动 5-7 后启动 5-6 + */ +int main(int argc, char *argv[]) { + if (argc <= 2) { + printf("usage: %s ip_address port_number\n", basename(argv[0])); return 1; } - const char* ip = argv[1]; - int port = atoi( argv[2] ); + const char *ip = argv[1]; + int port = atoi(argv[2]); struct sockaddr_in server_address; - bzero( &server_address, sizeof( server_address ) ); + bzero(&server_address, sizeof(server_address)); server_address.sin_family = AF_INET; - inet_pton( AF_INET, ip, &server_address.sin_addr ); - server_address.sin_port = htons( port ); + inet_pton(AF_INET, ip, &server_address.sin_addr); + server_address.sin_port = htons(port); - int sockfd = socket( PF_INET, SOCK_STREAM, 0 ); - assert( sockfd>= 0 ); - if ( connect( sockfd, ( struct sockaddr* )&server_address, sizeof( server_address ) ) < 0 ) - { - printf( "connection failed\n" ); - } - else - { - printf( "send oob data out\n" ); - const char* oob_data = "abc"; - const char* normal_data = "123"; - send( sockfd, normal_data, strlen( normal_data ), 0 ); - send( sockfd, oob_data, strlen( oob_data ), MSG_OOB ); - send( sockfd, normal_data, strlen( normal_data ), 0 ); + int sockfd = socket(PF_INET, SOCK_STREAM, 0); + assert(sockfd>= 0); + if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) { + printf("connection failed\n"); + } else { + printf("send oob data out\n"); + const char *oob_data = "abc"; + const char *normal_data = "123"; + send(sockfd, normal_data, strlen(normal_data), 0); + // 使用了 MSG_OOB 标志。MSG_OOB 标志表示发送紧急(out-of-band)数据。 + // 紧急数据是一种特殊的数据,通常用于在普通数据流中插入重要的消息。 + // 这里,紧急数据 "abc" 被发送到服务器。 + send(sockfd, oob_data, strlen(oob_data), MSG_OOB); + send(sockfd, normal_data, strlen(normal_data), 0); } - close( sockfd ); + close(sockfd); return 0; } diff --git a/5/5-7oobrecv.cpp b/5/5-7oobrecv.cpp index cd0b070..4d87de6 100644 --- a/5/5-7oobrecv.cpp +++ b/5/5-7oobrecv.cpp @@ -7,61 +7,74 @@ #include #include #include +#include #define BUF_SIZE 1024 -int main( int argc, char* argv[] ) -{ - if( argc <= 2 ) - { - printf( "usage: %s ip_address port_number\n", basename( argv[0] ) ); +/** + * ssize_t recv(int sockfd, void *buf, size_t len, int flags); + * 返回值:> 0 接收到的数据大小; + * == 0 另一端关闭了 socket; + * == -1 错误 + * + * 启动 5-7 后启动 5-6 : + * + * got 5 bytes of normal data '123ab' + * + * got 1 bytes of oob data 'c' 只有 c 被当成外带数据 + * + * got 3 bytes of normal data '123' + * + * 服务器对正常数据的接收将被带外数据截断,即前一部分正常数据"123ab"和后续的正常数据"123"是不能被一个recv调用全部读出的。 + */ + +int main(int argc, char *argv[]) { + if (argc <= 2) { + printf("usage: %s ip_address port_number\n", basename(argv[0])); return 1; } - const char* ip = argv[1]; - int port = atoi( argv[2] ); + const char *ip = argv[1]; + int port = atoi(argv[2]); struct sockaddr_in address; - bzero( &address, sizeof( address ) ); + bzero(&address, sizeof(address)); address.sin_family = AF_INET; - inet_pton( AF_INET, ip, &address.sin_addr ); - address.sin_port = htons( port ); + inet_pton(AF_INET, ip, &address.sin_addr); + address.sin_port = htons(port); - int sock = socket( PF_INET, SOCK_STREAM, 0 ); - assert( sock>= 0 ); + int sock = socket(PF_INET, SOCK_STREAM, 0); + assert(sock>= 0); - int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) ); - assert( ret != -1 ); + int ret = bind(sock, (struct sockaddr *) &address, sizeof(address)); + assert(ret != -1); - ret = listen( sock, 5 ); - assert( ret != -1 ); + ret = listen(sock, 5); + assert(ret != -1); struct sockaddr_in client; - socklen_t client_addrlength = sizeof( client ); - int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength ); - if ( connfd < 0 ) - { - printf( "errno is: %d\n", errno ); - } - else - { - char buffer[ BUF_SIZE ]; + socklen_t client_addrlength = sizeof(client); + int connfd = accept(sock, (struct sockaddr *) &client, &client_addrlength); + if (connfd < 0) { + printf("errno is: %d\n", errno); + } else { + char buffer[BUF_SIZE]; - memset( buffer, '0円', BUF_SIZE ); - ret = recv( connfd, buffer, BUF_SIZE-1, 0 ); - printf( "got %d bytes of normal data '%s'\n", ret, buffer ); + memset(buffer, '0円', BUF_SIZE); + ret = recv(connfd, buffer, BUF_SIZE - 1, 0); + printf("got %d bytes of normal data '%s'\n", ret, buffer); - memset( buffer, '0円', BUF_SIZE ); - ret = recv( connfd, buffer, BUF_SIZE-1, MSG_OOB ); - printf( "got %d bytes of oob data '%s'\n", ret, buffer ); + memset(buffer, '0円', BUF_SIZE); + ret = recv(connfd, buffer, BUF_SIZE - 1, MSG_OOB); + printf("got %d bytes of oob data '%s'\n", ret, buffer); - memset( buffer, '0円', BUF_SIZE ); - ret = recv( connfd, buffer, BUF_SIZE-1, 0 ); - printf( "got %d bytes of normal data '%s'\n", ret, buffer ); + memset(buffer, '0円', BUF_SIZE); + ret = recv(connfd, buffer, BUF_SIZE - 1, 0); + printf("got %d bytes of normal data '%s'\n", ret, buffer); - close( connfd ); + close(connfd); } - close( sock ); + close(sock); return 0; }

AltStyle によって変換されたページ (->オリジナル) /