网络编程-卷一 第3、4章套接字编程和基于TCP套接字编程
发布日期:2021-06-29 11:09:22 浏览次数:3 分类:技术文章

本文共 3591 字,大约阅读时间需要 11 分钟。

第3章 套接字编程简介

3.1、概述

套接字地址结构的传递主要是两个方向;从进程到内核、和从内核到进程,

地址转换函数;就是输入的是带.点的10进制数应该要转换为u32 int类型的数
大小端问题,本地操作系统大小端不确定,但是网络传输一般都是采用大端模式,及高位数据在低地址。

3.2、套接字地址结构

大多数套接字函数都是需要一个指向套接字地址结构的指针作为函数参数的,因此每个协议族都定义他自己的套接字地址结构,并且以socketaddr_开头。

3.2.1、IPV4的套接字地址结构 scoketaddr_in

在这里插入图片描述

在POSIX规范中只需要我们填充三个字段;sin_family、sin_addr、sin_port。

注意 IPV4地址和TCP/UDP端口号在套接字地址结构中总是以网络字节序来存储及大端模式,因此赋值时记得转换。

3.2.2、通用套接字地址结构 socketaddr

在这里插入图片描述

需要注意的是 因为套接字函数是在ANSI C之前定义的,因此这些函数使用的也都是struct socketaddr这个作为参数类型的,因此我们在使用IPV4,6对应套接字类型的时候必须要进行强制转换的。

int bind(int sockfd, const struct sockaddr *addr,                socklen_t addrlen);因此在使用的时候struct socketaddr_in seraddr;bind(sockfd, (const struct sockaddr *)&seraddr, sizeof(seraddr));//必须要强制转换,因为内核处理的时候是以sockaddr 格式去解析的

3.2.3、IPV6套接字地址结构 socketaddr_in6

在这里插入图片描述
3.2.4、新的通用套接字地址结构 socketaddr_storage
在这里插入图片描述

3.3、值 - 结果的传递 传递大小的到底传值还是指针

从进程到内核传递套接字 地址结构的函数有;bind、connect、sendto

他们其中都有两个参数是套接字地址结构的指针,和该结构体的大小,从而内核才知道到进程复制多大内存来解析

connect(sockfd, (const struct sockaddr *)&seraddr, sizeof(seraddr));

从内核到进程传递套接字 地址结构的函数有;accept、recvform、getsockname、getpeername;他们其中都有两个参数是套接字地址结构的指针,和该结构体的大小的整数变量的指针,对比为什么要返回整形变量的指针,在于需要传递结果回来,存储到这个整形变量里面

accept(sockfd, (struct sockaddr *)&cliaddr, &len);

3.4、字节排序函数;解决大小端问题

用来将主机short类型的字节顺序转为网络字节顺序。htons : h(host) to n(net) s (short): 用来将网络 short 类型的字节顺序转为主机字节顺序。ntohs : n(net) to h(host) s(short) :  用来将主机字节顺序转换为网络字节顺序,只不过转换变量的类型不同为 unsigned longhtonl : h(host) to n (net) l (long ) :用来将网络字节顺序转换为主机字节顺序,转换的变量为 unsigned longntohl:  n (net) to h(host) l (long) : ————————————————版权声明:本文为CSDN博主「zw1996」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/zw1996/article/details/114113581

3.5、字节操作函数

在这里插入图片描述
在这里插入图片描述
3.6、字符串和网络子序中的转换函数
在这里插入图片描述
在这里插入图片描述

3.9、实现readn、writen、readline函数

readline 读取的时候如果每读一个字符就read一下这样效率太低了,但是如果有一个缓冲的话就效率高很多了。

#include 
#include
#include
#include
#include
#include
#include
#include
#include
static int read_cnt;static char *read_ptr;static char read_buff[1000];//读取n个字符,返回读出的字节数int readLine(int fb, void *vpr, int n);static int Myread(int fb, char *vpr);int readLine_Quilt(int fb, void *vpr, int nmax);int main(){ int fb; fb = open("./test.txt", O_RDONLY); if (fb < 0) { printf("open: eror\n"); return -1; } char *p; p = (char *)malloc(sizeof(char)*100); while(1) { memset(p,0,sizeof(p)); if(readLine_Quilt(fb, p, 100) > 0) { if(p == NULL) break; printf("%s", p); } else { break; } } return 0;}static int Myread(int fb, char *vpr){ if(read_cnt <= 0) { if((read_cnt = read(fb, read_buff, sizeof(read_buff))) < 0) { return -1; } else if(read_cnt == 0) { return 0; } read_ptr = read_buff; } read_cnt--; *vpr = *read_ptr++; return 1;}int readLine_Quilt(int fb, void *vpr, int nmax){ char *ptr = vpr; char c; int nread; int n; for( n = 1; n < nmax; n++) { if((nread = Myread(fb, &c)) == 1)//有个缓冲,先读到存储到那里, { *ptr++ = c; if(c == '\n')break; } else if(nread == 0) { *ptr = 0; return n-1; } else { return -1; } } *ptr = 0; return n;}int readLine(int fb, void *vpr, int nmax){ char *ptr = vpr; char c; int nread; int n; for( n = 1; n < nmax; n++) { if((nread = read(fb, &c, 1)) == 1)//每读一个字节就要read一下,效率低 { *ptr++ = c; if(c == '\n')break; } else if(nread == 0) { *ptr = 0; return n-1; } else { return -1; } } *ptr = 0; return n;}

第4章 基于TCP套接字编程

4.1、概述一个完成的TCP客户端/服务器程序

在这里插入图片描述
4.2、socket函数
为了执行网络IO,则一个进程必须做的一件事情就是调用socket函数,指定期望的通信协议类型,也就是要执行IO通信通道所支持的协议类型进行指定。

int socket(int domain, int type, int protocol);domain;表示网络域,就是网络范围,ipv4还是ipv6有相关宏设置AF_INET、AF_INET6type;通信协议的类型,tcp,udp...也有相关的宏来设置protocol  一般传0表示无特例,默认协议

在这里插入图片描述

在这里插入图片描述

也可查看这篇对socket接口的基本介绍和案例

https://blog.csdn.net/zw1996/article/details/114113581

转载地址:https://blog.csdn.net/zw1996/article/details/114281182 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:C++面向对象思维刷题
下一篇:海思项目学习记录 -3、ORTP库传输

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2024年04月22日 18时46分28秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章