当前位置:首页 > 嵌入式 > 嵌入式教程
[导读]以前都只是在网上搜的能用的例子,对一些参数不是很清楚,这次汇总。而且网络通信还是很常用的通信手段。

以前都只是在网上搜的能用的例子,对一些参数不是很清楚,这次汇总。而且网络通信还是很常用的通信手段。

UNIX 环境高级编程对Socket通信的描述是套接字网络IPC(进程间通信),可以用于计算机间通信也可用于计算机内通信,管道、消息队列、信号量以及共享内存等都是属于计算机内通信的情况。

一、 套接字Api详细介绍

1. 套接字描述符

首先会先到的是文件描述符,对Linux一切皆文件的哲学又多懂了一点儿点儿。

套接字是通信端点的抽象。与应用程序使用文件描述符一样,访问套接字需要使用套接字描述符。套接字描述符在UNIX系统是用文件描述符实现的。

#include int socket (int domain, int type, int protocal);返回值:成功返回文件(套接字)描述符,出错返回-1

参数domain(域)确定通信的特性,包括地址格式。各个域都有自己的格式表示地址,表示各个域的常数都以AF_开头,意指地址族(address family).

参数type确定套接字的类型,进一步确定通信特征。下图给出了一些类型,但在实现中可以自由增加对其他类型的支持。

参数protocol通常是0,表示按给定的域和套接字类型选择默认的协议。当对同一域和套接字类型支持多个协议时,可以使用proticol参数选择一个特定协议。在A_FINET通信域中套接字类型SOCK_STREAM的默认协议是TCP(传输控制协议);A_FINET通信域中套接字类型SOCK_DGRAM的默认协议是UDP(用户数据报协议)。

字节流(SOCK_STREAM)要求在交换数据之前,在本地套接字和远程套接字之间建

立一个逻辑联系。

Tcp:没有报文界限,提供的是字节流服务。之前写过Qt传输图片的拆包与解包,原因就是如此吧。

调用socket与调用open类型,均可获得用于输入、输出的文件描述符。不用的时候记得close关闭。

2. 寻址

如何确定一个目标通信进程?

进程的标识有两个部分:计算机的网络地址可以确定网络上与之想要通信的计算机

服务可以确定计算机上的特定进程。

2.1 字节序

在同一台计算机上进程间通信时,一般无需考虑字节序。

TCP/IP协议栈使用大端字节序。有关字节序大家可自行百度。

Linux系统是小端字节序。

2.2 地址格式

地址确定了特定通信域中的套接字端点,地址格式与特定的通信域相关。为使不同格式的地址能够被传入到套接字函数,地址被强转换成通用的地址结构sockaddr表示。

Linux中,sockaddr_in定义如下:

struct sockaddr_in {sa_family_t sin_family;in_port_t sin_port;struct in_addr sin_addr;unsigned char sin_zero[8];};

其中成员sin_zero为填充字段,必须全部置0. 所以在网上搜到的例子有使用bzero.

我目前使用的ubuntu定义如下:

/* Structure describing an Internet socket address. */struct sockaddr_in { __SOCKADDR_COMMON (sin_); in_port_t sin_port; /* Port number. */ struct in_addr sin_addr; /* Internet address. */ /* Pad to size of `struct sockaddr'. */ unsigned char sin_zero[sizeof (struct sockaddr) - __SOCKADDR_COMMON_SIZE - sizeof (in_port_t) - sizeof (struct in_addr)]; };

还有很多关于地址查询的函数,这里就不一一列举了。

3. 将套接字与地址绑定

使用bind函数将地址绑定到一个套接字上。

#include int bind(int sockfd, const struct sockaddr * addr, socklen_t len);返回值:成功返回0,出错返回-1

参数socklen_t使用sizeof来计算就好了。

对于使用地址的一些限制:

端口号不能小于1024,除非该进程具有相应的特权(即为超级用户)。可见规则总是因人而异,计算机也是如此~

对于因特网域,如果指定IP地址为ADDR_ANY,套接字端点可以被绑定到所有的系统网络接口。

注意:linux的man命令可以查看api的详细说明,而且还有例子,也挺不错的。

4. 建立连接

1> connect

如果处理的是面向连接的网络服务(SOCK_STREAM或SOCK_SEQPACKET),在开始交换数据前,需要在请求服务的进程套接字(客户端)和提供服务的进程套接字(服务器)之间建立一个连接。使用connect.

#include int connect(int sockfd, const struct sockaddr *addr, socklen_t len);返回值:成功返回0,出错返回-1

诶,这个参数好熟悉呀,和bind函数的参数一模一样呀~

当client连接server时,由于一些原因,连接可能会失败。可以使用指数补偿的算法解决,了解一下即可。

2> listen

server调用listen来宣告可以接受连接请求:

#include Int listen(int sockfd, int backlog);返回值:成功返回0,出错返回-1

参数backlog提供了一个提示,用于表示该进程所要入队的连接请求数量。其值由系统决定,但上限由中SOMAXCONN指定。

一旦队列满,系统会拒绝多余的连接请求。

3> accept

一旦服务器调用了listen,套接字就能接收连接请求。使用函数accept获得连接请求并建立连接。

#include Int accept(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict len);返回值:成功返回文件(套接字)描述符,出错返回-1

函数accept所返回的文件描述符是套接字描述符,该描述符连接到调用connect的客户端。这个新的套接字描述符和原始套接字(sockfd)具有相同的套接字类型和地址族。传给accept的原始套接字没有关联到这个连接,而是继续保持可用状态并接受其他连接请求。

如果不关心客户端标识,可以将addr和len设置为NULL,否则addr存放的是连接的客户端的地址。

如果没有连接请求等待处理,accept会阻塞直到有请求到来。另外server可以使用poll或select来等待一个请求的到来。

5. 数据传输

既然将套接字端点表示为文件描述符,那么只要建立连接,就可以使用read和write来通过套接字通信。read和write函数我几乎不用,了解一下即可。

1> send

#include Int send(int sockfd, const void *buf, size_t nbytes, int flags);返回值:成功返回发送的字节数,出错返回-1

注意:如果send成功返回,并不一定并表示连接的另一端的进程接收数据。可以保证的是数据已经无误的发送到网络上。

标志我一直用的是0

2> recv

#include int recv(int sockfd, const void *buf, size_t nbytes, int flags);返回值:以字节计数的消息长度,若无可用消息或对方已经按序结束则返回0, 出错返回-1

仍然一直是0

如果想定位发送者,可以使用recvfrom来得到数据发送者的源地址。

3> recvfrom

#include int recv(int sockfd, void *restrict buf, size_t len, int flag, struct sockaddr *restrict addr, socklen_t *restrict len);返回值:以字节计数的消息长度,若无可用消息或对方已经按序结束则返回0, 出错返回-1

因为可以获得发送者的地址,recvfrom通常用于无连接套接字。否则,recvfrom等同于recv。

二、 小结

这里面再提一个带外数据,感兴趣的同志可以自行百度。

之前写过一个server和client的例子,连接如下,可对应本文做对比阅读。

LinuxSocket Server 与 Client 例子

个人觉得这只是套接字的入门,如果一个服务器要连接多个客户端呢?以后有机会和大家一起分享下select的套接字用法。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

双系统将是下述内容的主要介绍对象,通过这篇文章,小编希望大家可以对双系统的相关情况以及信息有所认识和了解,详细内容如下。

关键字: 双系统 Windows Linux

安装Linux操作系统并不复杂,下面是一个大致的步骤指南,以帮助您完成安装。1. 下载Linux发行版:首先,您需要从Linux发行版官方网站下载最新的ISO镜像文件。

关键字: Linux 操作系统 ISO镜像

计算机是由一堆硬件组成的,为了有限的控制这些硬件资源,于是就有了操作系统的产生,操作系统是软件子系统的一部分,是硬件基础上的第一层软件。

关键字: Linux 操作系统 计算机

Linux操作系统是一套免费使用和自由传播的类Unix操作系统,通常被称为GNU/Linux。它是由林纳斯·托瓦兹在1991年首次发布的,并基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。Lin...

关键字: Linux 操作系统

所谓进程间通信就是在不同进程之间传播或交换信息,它是一组编程接口,让程序员能够协调不同的进程,使之能在一个操作系统里同时运行,并相互传递、交换信息;还可以让一个程序能够在同一时间里处理许多用户的需求。

关键字: Linux 进程通信 编程接口

串口通信作为一种最传统的通信方式,在工业自动化、通讯、控制等领域得到广泛使用。

关键字: Linux 串口通信 通讯

2023年11月16日: MikroElektronika(MIKROE) ,作为一家通过提供基于成熟标准的创新式硬软件产品来大幅缩短开发时间的嵌入式解决方案公司,今天宣布推出一款基于单线设备的软硬件开源解决方案Cli...

关键字: 嵌入式 Linux 操作系统

Linux是一种免费使用和自由传播的类Unix操作系统,其内核由林纳斯·本纳第克特·托瓦兹于1991年10月5日首次发布。它主要受到Minix和Unix思想的启发,是一个基于POSIX的多用户、多任务、支持多线程和多CP...

关键字: Linux 操作系统

本文中,小编将对嵌入式予以介绍,如果你想对它的详细情况有所认识,或者想要增进对它的了解程度,不妨请看以下内容哦。

关键字: 嵌入式 Linux

在这篇文章中,小编将为大家带来嵌入式 Linux的相关报道。如果你对本文即将要讲解的内容存在一定兴趣,不妨继续往下阅读哦。

关键字: 嵌入式 Linux
关闭
关闭