完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本帖最后由 michael_llh 于 2016-11-1 20:44 编辑
本次我们将要来谈一谈关于socket编程的简单实现,总的实现下来发现有这样的一个特点,对于底层的语言C来实现socket是比较麻烦的,相反的对于高级语言python和java这一类的高级语言是比较容易实现的,代码量比较小,同时也比较容易理解。虽然C语言在配置上面稍微麻烦了一点,但是对于socket来说还好,也算可以接收,我们等下具体看下实现的方式。因为对于socket而言的话是有套路的,它的流程是固定的所以我们直接按照步骤一步一步来完成就可以了。 开始进入代码的时候我们先来看下我们编程中将会用到的相关API函数。 1.首先是socket函数,包含的头文件如下 #include #include 函数的原型如下: int socket(int domain, int type, int protocol); 输入参数: int domain:这里需要注意这里不是域名的意思,一开始我以为是填入域名的意思,就想把IP填进去了,但是这里的意思是范围领域的意思,可以填入的参数如下: Name Purpose Man page AF_UNIX, AF_LOCAL Local communication unix(7) AF_INET IPv4 Internet protocols ip(7) AF_INET6 IPv6 Internet protocols ipv6(7) AF_IPX IPX - Novell protocols AF_NETLINK Kernel user interface device netlink(7) AF_X25 ITU-T X.25 / ISO-8208 protocol x25(7) AF_AX25 Amateur radio AX.25 protocol AF_ATMPVC Access to raw ATM PVCs AF_APPLETALK Appletalk ddp(7) AF_PACKET Low level packet interface packet(7) int type:顾名思义就是类型了,表示的是套接字的数据类型如下: SOCK_STREAM 字节流 SOCK_DGRAM 数据报 SOCK_SEQPACKET 有序数组 SOCK_RAW 原始套接口 等等。。 这里还要注意一点,就是这里的数据类型要和协议对应。 int protocal:默认我们直接使用0填入这个参数即可。 指定相应的传输协议,也就是诸如TCP或UDP协议等等,系统针对每一个协议簇与类型提供了一个默认的协议,我们通过把protocol设置为0来使用这个默认的值。注意这里的协议与上面的协议簇是两个不同的概念,前者是指网络层的协议,由于它对于到传输层会出现许多协议,比如IPv4可以用来实现TCP或UDP等等传输层协议,所以称为协议簇。相应的传输层的协议就简单地称为协议。常见的协议有TCP、UDP、SCTP,要指定它们分别使用宏IPPROTO_TCP、IPPROTO_UPD、IPPROTO_SCTP来指定。 到linux/in.h看可以使用哪些传输层的协议。 返回值:成功的话返回一个套接字描述符,和我们的文件描述符是类似的,我们通过这个文件描述符进行相应的读写操作。错误的话返回-1,并设置errno. 2.bind函数 需要包含的头文件: #include #include 函数原型: int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 输入参数: int sockfd:这里填入的就是调用socket创建得到的套接字描述符 const struct sockaddr *addr, socklen_t addrlen):这个是一个socket地址信息的结构体,定义如下: struct sockaddr { sa_family_t sa_family; char sa_data[14]; } socklen_t addrlen:这个就是我们传入的结构体有多长 返回值:成功的话返回0,或者返回-1,同时设置errno 3.listen函数 包含的头文件: #include #include 函数原型: int listen(int sockfd, int backlog); 输入参数: int sockfd:同样传入socket创建得到的套接字描述符 int backlog:规定了内核应该为相应套接口排队的最大连接个数。这个参数比较是深入,具体可以参考Unix网络编程中进行查阅。 返回值:如果成功返回0,错误返回-1,同时设置errno 4.accept函数 应包含的头文件: #include #include 函数原型: int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); 输入参数: int sockfd:同样填入socket创建得到的sockfd描述符 struct sockaddr *addr:这是一个输出型参数,这个函数会阻塞在这里等待客户端连接,连接成功之后可以获取客户端的相关信息 socklen_t *addrlen:同样的表示我们传入的这个结构体有多大 返回值:这里的返回值比较特殊,我们需要通过这个返回值进行数据的读写,是从服务端的角度来说,这里还是类似返回的是一个文件描述符。 5.send函数 应包含的头文件: #include #include 函数原型: ssize_t send(int sockfd, const void *buf, size_t len, int flags); 输入参数: int sockfd:对于服务端来说,这里填入的是accept的返回值,而对于服务端是填入socket返回值 const void *buf:传入我们的数据 size_t len:数据的大小 int flags:标志位的话可以设置很多方式,这里我们默认选择为0就可以了 返回值:表示成功发送了多少个字节的数据 6.recv函数 应包含的头文件: #include #include 函数原型: ssize_t recv(int sockfd, void *buf, size_t len, int flags); 输入参数: int sockfd:对于服务端来说,这里填入的是accept的返回值,而对于服务端是填入socket返回值 const void *buf:传入我们的数据 size_t len:数据的大小 int flags:标志位的话可以设置很多方式,这里我们默认选择为0就可以了 返回值:表示成功接收了多少个字节的数据 7.connect函数 应该包含的头文件: #include #include 函数原型:(客户端使用的连接服务端的函数) int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 输入参数: int sockfd:填入socket函数的返回值,套接字描述符 const struct sockaddr *addr:填入服务端的一些地址信息,像IP地址和端口信息等等 socklen_t addrlen:第二个参数结构体的大小 返回值:成功的话返回0,错误的话返回-1,同时设置errno、 大概我们会使用到的函数就是这7个了,但是总结的可能细节做的不够好,理解的还不是特别好,后面再慢慢补充这些内容。 我们实践实现的内容为客户端发送注册信息,服务端接收注册信息,同时在服务端将注册的学生信息打印出来,代码如下,参考了朱有鹏老师的代码: 服务端:
客户端:
|
|
相关推荐
2 个讨论
|
|
只有小组成员才能发言,加入小组>>
「含关键代码」基于AM3352/AM3354/AM3359的Linux开发案例分享
4866 浏览 0 评论
87350 浏览 0 评论
【高手问答】如何做到精通linux技术?资深工程师带你突破难点
4670 浏览 2 评论
3562 浏览 2 评论
解读Linux :先从创建一个文件夹用来存放jdk压缩文件开始
2449 浏览 0 评论
1945浏览 3评论
这是i.mx6ull的关于usb的宏定义,能解释下这些宏定义的意思
1315浏览 1评论
1219浏览 1评论
求解:aarch64交叉编译工具已经安装成功,环境变量已经配置,怎么将系统架构切换为ARM的架构
1288浏览 0评论
电脑和虚拟机可以互ping,电脑和开发板也可以互ping,但是虚拟机和开发板ping不通是什么原因
1206浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-19 04:26 , Processed in 0.931102 second(s), Total 46, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号