Linux之socket网络编程(全)

1、什么是套接字socket

套接字(socket) 是一种通信机制,凭借这种机制,客户/服务器系统的开发工作既可以在本地单
机上进行,也可以跨网络进行。Linux所提供的功能( 如打印服务、连接数据库和提供Web页面)和网
络工具(如用于远程登录的rlogin和用于文件传输的ftp)通常都是通过套接字来进行通信的。套接字的创建和使用与管道是有区别的,因为套接字明确地将客户和服务器区分开来。套接字机制可以实现将多个客户连接到一个服务器。

2、主机字节序列和网络字节序列

(1)当在基于Intel处理器的Linux机器上运行新版本的服务器和客户程序时,我们可以用netstat命令来查看网络连接状况。这个命令在大多数配置了网络功能的UNIX系统上都能找到。它显示了客户/服
务器连接正在等待关闭。连接将在一小段超时时间之后关闭(具体的输出内容将随Linux版本的不同
而不同)。
(2)主机字节序列分为大端字节序和小端字节序,不同的主机采用的字节序列可能不同。大端字节序是指一个整数的高位字节存储在内存的低地址处,低位字节存储在内存的高地址处。小端字节序则是指整数的高位字节存储在内存的高地址处,而低位字节则存储在内存的低地址处。在两台使用不同字节序的主机之间传递数据时,可能会出现冲突。所以,在将数据发送到网络时规定整形数据使用大端字节序,所以也把大端字节序成为网络字节序列。对方接收到数据后,可以根据自己的字节序进行转换。
Linux 系统提供如下 4 个函数来完成主机字节序和网络字节序之间的转换:

include <netinet/in.h>

uint32_t htonl(uint32_t hostlong); // 长整型的主机字节序转网络字节序

uint32_t ntohl(uint32_t netlong); // 长整型的网络字节序转主机字节序

uint16_t htons(uint16_t hostshort); // 短整形的主机字节序转网络字节序

uint16_t ntohs(uint16_t netshort); // 短整型的网络字节序转主机字节序

2、套接字地址结构

2.1 通用 socket 地址结构

socket 网络编程接口中表示 socket 地址的是结构体 sockaddr,其定义如下:

#include <bits/socket.h>
 struct sockaddr
 {
 sa_family_t sa_family;
 char sa_data[14];
 };

sa_family 成员是地址族类型(sa_family_t)的变量。地址族类型通常与协议族类型对应。常见的协议族和对应的地址族如下图所示:
在这里插入图片描述

2.2 专用 socket 地址结构

TCP/IP 协议族有 sockaddr_in 和 sockaddr_in6 两个专用 socket 地址结构体,它们分别用于 IPV4 和 IPV6:

 struct in_addr
 {
 u_int32_t s_addr;
 };
 struct sockaddr_in
{
 sa_family_t sin_family;
 u_int16_t sin_port;
 struct in_addr sin_addr;
};
struct in6_addr
{
 unsigned char sa_addr[16]; // IPV6 地址,要用网络字节序表示
};
struct sockaddr_in6
{
 sa_family_t sin6_family; // 地址族:AF_INET6
 u_inet16_t sin6_port; // 端口号:用网络字节序表示
 u_int32_t sin6_flowinfo; // 流信息,应设置为 0
 struct in6_addr sin6_addr; // IPV6 地址结构体
 u_int32_t sin6_scope_id; // scope ID,尚处于试验阶段
 };
  • sin_family: 地址族 AF_INET
  • sin_port: 端口号,需要用网络字节序表示
  • sin_addr: IPV4 地址结构:s_addr 以网络字节序表示 IPV4 地址

2.3 IP 地址转换函数

通常,人们习惯用点分十进制字符串表示 IPV4 地址,但编程中我们需要先把它们转化为整数方能使用,下面函数可用于点分十进制字符串表示的 IPV4 地址和网络字节序整数表示的 IPV4 地址之间的转换:

#include <arpa/inet.h>
in_addr_t inet_addr( const char *cp); //字符串表示的 IPV4 地址转化为网络字节序
char* inet_ntoa( struct in_addr in); // IPV4 地址的网络字节序转化为字符串表示

3、网络编程接口

头文件

#include <sys/types.h>
#include <sys/socket.h>
  • int socket( int domain, int type, int protocol);
socket()创建套接字,成功返回套接字的文件描述符,失败返回-1 domain: 设置套接字的协议簇, AF_UNIX AF_INET AF_INET6
type: 设置套接字的服务类型 SOCK_STREAM SOCK_DGRAM
protocol: 一般设置为 0,表示使用默认协议
  • int bind( int sockfd, const struct sockaddr *addr, socklen_t
    addrlen);
bind()将 sockfd 与一个 socket 地址绑定,成功返回 0,失败返回-1
sockfd 是网络套接字描述符
addr 是地址结构
addrlen 是 socket 地址的长度
  • int listen( int sockfd, int backlog);
listen()创建一个监听队列以存储待处理的客户连接,成功返回 0,失败返回-1
sockfd 是被监听的 socket 套接字
backlog 表示处于完全连接状态的 socket 的上限
  • int accept( int sockfd, struct sockaddr *addr, socklen_t *addrlen);
accept()从 listen 监听队列中接收一个连接,成功返回一个新的连接 socket,该 socket 唯一地标识了被接收的这个连接,失败返回-1
 sockfd 是执行过 listen 系统调用的监听 socket
 addr 参数用来获取被接受连接的远端 socket 地址
 addrlen 指定该 socket 地址的长度
  • int connect( int sockfd, const struct sockaddr *serv_addr, socklen_t
    addrlen);
connect()客户端需要通过此系统调用来主动与服务器建立连接,成功返回 0,失败返回-1
sockfd 参数是由 socket()返回的一个 socket。
serv_addr 是服务器监听的 socket 地址
addrlen 则指定这个地址的长度
  • int close( int sockfd);
close()关闭一个连接,实际上就是关闭该连接对应的 socket
  • ssize_t recv( int sockfd, void *buff, size_t len, int flags);
  • ssize_t send( int sockfd, const void *buff, size_t len, int flags);
TCP 数据读写:
 recv()读取 sockfd 上的数据,buff 和 len 参数分别指定读缓冲区的位置和大小
 send()往 socket 上写入数据,buff 和 len 参数分别指定写缓冲区的位置和数据长度
 flags 参数为数据收发提供了额外的控制
  • ssize_t recvfrom( int sockfd, void buff, size_t len, int
    flags,struct sockaddr
    src_addr, socklen_t*addrlen);
  • ssize_t sendto( int sockfd, void buff, size_t len, int flags,struct
    sockaddr
    dest_addr, socklen_t addrlen);
UDP 数据读写:
 recvfrom()读取 sockfd 上的数据,buff 和 len 参数分别指定读缓冲区的位置和大小
 src_addr 记录发送端的 socket 地址
 addrlen 指定该地址的长度
sendto()往 socket 上写入数据,buff 和 len 参数分别指定写缓冲区的位置和数据长度
 dest_addr 指定接收数据端的 socket 地址
 addrlen 指定该地址的长度
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值