Linux服务器开发(基础篇):网络编程相关函数详解

引言

现在QQ、微信等聊天软件在我国得到了广泛使用,其火热程度可以说是:一天不吃饭也不能一天不聊微信。那么你可知道,手机上的软件是如何互相通信的呢?有计算机网络基础的读者,肯定很容易知道答案:通过网络套接字就可以通信了。

简单介绍

那啥是网络套接字呢?简单来说,它由三个部分组成:对方IP地址、使用的传输层协议(TCP或UDP)和端口号。其中IP地址能唯一标识出全球网络中联网了的一台主机,传输层协议是指通信双方以哪种数据传输的方式进行数据交互,端口号能代表是哪个程序(其实这里应该是进程)在进行通信。打个比方,IP地址代表了一对小情侣双方的家庭住址,通信双方代表了他们去对方家里时的交通方式,端口号则代表了这对小情侣,这样小情侣在串门的时候就不会走错,也不会找错恋爱对象了。

对Linux中一切皆文件的解释

在Linux系统层面的设计上,是使用了一种面向对象的设计思想,将一切外设当做文件,从而可以使用针对文件的那些操作。任何东西都挂在文件系统之上,即便即使它们不是文件,也以文件的形式来呈现,比如C语言当中的stdin、stdout等,在fprintf、read、write函数中,都可以通过文件描述符来对相应的设备(或者文件)进行输入输出;再比如proc、dev、socket等,都可以像操作文件一样对它们进行操作。
有了这个知识,接下来就可以来看看socket编程的相关函数了。

Socket相关函数定义及其功能

创建套接字并返回文件描述符

#include <sys/types.h> 
#include <sys/socket.h>
int socket(int domain, int type, int protocol);

参数含义:
domain:
AF_INET(现在基本上都是使用这个) 这是大多数用来产生socket的协议,使用TCP或UDP来传输,用IPv4的地址
AF_INET6 与上面类似,不过是来用IPv6的地址
AF_UNIX 本地协议,使用在Unix和Linux系统上,一般都是当客户端和服务器在同一台及其上的时候使用
type:
SOCK_STREAM 这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类型,这个socket是使用TCP来进行传输。
SOCK_DGRAM 这个协议是无连接的、固定长度的传输调用。该协议是不可靠的,使用UDP来进行它的连接。
SOCK_SEQPACKET该协议是双线路的、可靠的连接,发送固定长度的数据包进行传输。必须把这个包完整的接受才能进行读取。
SOCK_RAW socket类型提供单一的网络访问,这个socket类型使用ICMP公共协议。(ping、traceroute使用该协议)
protocol:
传0 表示使用默认协议。
返回值:
成功:返回指向新创建的socket的文件描述符,失败:返回-1,设置errno

将socket与IP地址、端口号等字段组成的结构体绑定

#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数含义:
sockfd:
服务器端socket文件描述符
addr:
构造出IP地址加端口号
addrlen:
sizeof(addr)长度
返回值:
成功返回0,失败返回-1, 设置errno

监听等待连接

#include <sys/types.h> 
#include <sys/socket.h>
int listen(int sockfd, int backlog);

参数含义:
sockfd:
服务器端socket文件描述符
backlog:
在Linux 系统中,它是指排队等待建立3次握手队列长度
返回值:
监听成功返回1,失败返回-1,设置errno

listen成功后,接收连接请求并返回一个新的socket用来通信

#include <sys/types.h> 	
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

参数含义:
sockdf:
服务器端socket文件描述符
addr:
传出参数,返回链接客户端地址信息,含IP地址和端口号
addrlen:
传入传出参数(值-结果),传入sizeof(addr)大小,函数返回时返回真正接收到地址结构体的大小
返回值:
成功返回一个新的socket文件描述符,用于和客户端通信,失败返回-1,设置errno

扫描二维码关注公众号,回复: 14723829 查看本文章

客户端与服务器端连接

#include <sys/types.h> 					
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数含义:
sockdf:
客户端socket文件描述符
addr:
传入参数,指定服务器端地址信息,含IP地址和端口号
addrlen:
传入参数,传入sizeof(addr)大小
返回值:
成功返回0,失败返回-1,设置errno

当connect成功后,客户端A的sockfd就已经能与服务器端B进行通信了,且服务器端B的accept函数也将成功返回一个sockfd,用来专门标识A与B连接,并可使用sockfd与A通信。值得注意的是,每当不同的客户端成功connect到服务器后,accept返回的sockfd是标识着不同的连接,每次都不一样。

出错处理函数定义及其功能

返回出错原因

#include <errno.h>
#include <string.h>
char *strerror(int errnum);

参数含义:
errnum:
传入参数,错误编号的值,一般取 errno 的值
返回值:
错误原因

向stderr(标准出错)输出错误原因

#include <stdio.h>
#include <errno.h>
void perror(const char *s);

参数含义:
s:传入参数,自定义的描述

常用文件操作函数定义及其功能

向fd所标识的文件中写入最大为count字节大小的buf

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

参数含义:
fd:
文件描述符
buf:
写入的数据
count:
写入的最大长度
返回值:
成功:返回实际写入的字节数;
失败:返回 -1, 错误编号设置 errno

从fd所标识的文件中读取count个字节到buf里面

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

参数含义:
fd:
文件描述符
buf:
存放读取数据的地方
count:
最大读取长度
返回值:
大于等于0:代表读取的长度
-1:出错了,设置errno

关闭fd所标识的文件(回收资源),成功后该文件描述符可以再次被分配使用

#include <unistd.h>
int close(int fd);

参数含义:
fd:
文件描述符
返回值:
成功: 0
失败: -1,设置errno

注意,某个socket不再使用时,我们应当用close将该资源回收,否则在并发环境下,可能会出现描述符被占用的错误,造成通信失败。
预告:下一篇将更新一个简单的聊天服务器案例,后续章节将对该服务器进行逐步改进。

猜你喜欢

转载自blog.csdn.net/weixin_45416439/article/details/125954173
今日推荐