linux socket编程1

112 篇文章 4 订阅
3 篇文章 0 订阅
主机是指网络上到一个节点,不能简单的理解为一个计算机,实际上IP地址是分配给计算机的网络适配器(即网卡)的,
一台计算机可以有多个网络适配器,也就可以有多个IP地址,一个网卡就是一个网络节点。
IPv4地址为32位地址,一般以4个字节表示。每个字节到数字用十进制表示,即每个节点的数的范围是0~255,且每个
数字之间用点隔开,例如:192.168.0.122,这种记录方法称为“点-分”十进制记号法。IP地址到结构如下所示:
| 网络类型 | 网络ID | 主机ID |
Internet地址可以分为5类
地址类型    第一个字节的十进制值
  A             000-127
  B             128-191
  C             192-233
  D             224-239
  E             240-255
A、B、C 三类由InterNIC(Internet网络信息中心)在全球范围内统一分配,D、E为特殊地址。

端口号
TCP/UDP协议使用16位整数存储端口号,每个主机拥有65535个端口。
一些端口被IANA分配给指定应用
21:FTP
23:Telnet
80:HTTP
RFC 1700(大约有2000个保留端口)
linux中文件/etc/service记录了已经占用的端口。

Socket是一种通讯机制,它包含一整套的调用接口和数据结构的定义,它给应用程序提供了使用如TCP/UDP等网络协议
进行网络通讯到手段。
linux中的网络编程通过Socket接口实现,Socket即是一种特殊到IO,提供对应的文件描述符。一个完整的Socket都
有一个相关描述(socket五元组){协议,本地地址,本地端口,远程地址,远程端口};每一个Socket都有一个本地的
唯一Socket,由操作系统分配。

创建Socket
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
返回值:成功返回描述符,错误返回-1
Socket创建在内核中,若创建成功返回内核文件描述表中的socket描述符(socket套接字实际上就是一个内核中到结构
体)。
domain:
    AF_INET     IPv4因特网域
    AF_INET6    IPv6因特网域
    AF_UNIX     unix域
    AF_UNESPEC  未指定
type:
    SOCK_STREAM     流式套接字可以提供可靠的、面向连接的通讯流。它使用了TCP协议。TCP保证了数据传输的正
                    确性和顺序性
    SOCK_DGRAM      数据报套接字定义了一种无连接到服务,数据通过相互独立到报文进行传输,是无序的,并且不
                    保证可靠、无差错。使用数据报协议UDP协议。
    SOCK_RAW        原始套接字允许对底层协议如IP或ICMP直接访问,主要用于新的网络协议实现到测试等。
    SOCK_SEQPACKET  长度固定、有序、可靠面向连接报文传递
protocol:
    通常为0,表示给指定的域和套接字类型选择默认协议
    
字节序
不同体系结构的主机使用不同的字节序存储器保存多字节整数。字节存储顺序不同,有的系统是高位在前,低位在后(大端字节序),
有的系统是低位在前,高位在后(小端字节序列)。网络协议使用网络字节序,即大端字节序。网络传输的数据大家是一定要统一
顺序的,所以对于内部字节表示顺序和网络字节顺序不同的机器,就一定要对数据进行转换。
uint32_t htonl(uint32_t hostlong);
    将一个32位整数由主机字节序转换为网络字节序
uint16_t htons(uint16_t hostshort);
    将一个16位整数由主机字节序转换为网络字节序
uint32_t ntohl(uint32_t netlong);
    将一个32位整数由网络字节序转换为主机字节序
uint16_t ntohs(uint16_t netshort);
    将一个16位整数由网络字节序转换为主机字节序
注:函数内部会自己判断所使用到机器使用的是何种字节序,然后完才字节序转换。

通用地址结构
#include <sys/socket.h>
struct sockaddr
{
    unsigned short sa_family;//Internet地址族,AF_XXX
    char sa_data[14];//14 bytes的协议地址
};
sa_data包含了一些远程电脑的地址、端口和套接字的数目,它里面的数据是冗杂在一起的。
sa_family一般来说,IPv4使用AF_INET。
在传递给需要地址结构到函数时,把指向地址结构的指针转换成(struct sockaddr*)传递进去。

因特网地址结构
struct in_addr
{
    in_addr_t s_addr; //IPv4地址
};

struct sockaddr_in
{
    short int sin_family;//Internet地址族如AF_INET
    unsigned short int sin_port;//端口号,16位值(网络字节序)
    struct in_addr sin_addr;//Internet的地址,32位IPv4地址(网络字节序)
    unsigned char sin_zero[8];//填0(为了格式对齐的填充位)
};

通用地址结构与因特网地址结构数据类型是等效的,可以相互转换,通常使用sockaddr_in更为方便。

IPv4地址族和字符地址之间到转换
#include <arp/inet.h>
const char* inet_ntop(int domain, const void *restrict addr, char* restrict str, socklen_t size);
返回:成功返回地址字符串指针,出错返回NULL
功能:网络字节序转换成点分十进制

int inet_pton(int domain, const char* restrict str, void *restrict, addr);
返回:成功返回1,无效格式返回0,出错返回-1
功能:点分十进制转换:为网络字节序

参数:
domain:Internet地址族,如AF_INET
addr:Internet地址,32位IPv4地址(网络字节序)
str:地址字符串(点分十进制)指针
size:地址字符串大小

填写IPv4地址族结构案例:
struct sockaddr_in sin; //定义一个sockaddr_in结构体
char buf[16];
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;//填写Internet地址族
sin.sin_port = htons((short)3001);//填写端口号(网络字节序)

//填充sin_addr
if(inet_pton(AF_INET, "192.168.1.1", &sin.sin_addr.s_addr) < 0)
{
    //错误处理
}
printf("%s\n", inet_ntop(AF_INET, &sin.sin_addr.s_addr, buf, sizeof(buf)));


TCP客户端服务器编程模型
客户端调用序列:
1.调用socket函数创建套接字
2.调用connect连接服务器端
3.调用I/O函数(read/write)与服务器端进行通信
4.调用close关闭套接字
Socket(tcp)的客户端编程步骤:
1) 在内核中创建结构体struct socket
2) 用户空间中创建地址结构体struct sockadd_in
3) 往地址结构体中加入服务器的ip和port并要将其转成网络字节序
4) 发送连接请求给服务器(connect)
5) 通过socket发送和接受数据(write and read)
6) 释放资源(close)

服务器端调用序列:
1.用socket函数创建套接字
2.调用bind绑定本地地址和端口
3.调用listen启动监听
4.调用accept从已连接队列中提取客户连接
5.调用I/O函数(read/write)与客户端进行通信
6.调用close关闭套接字

 服务器编程步骤:
1) 在内核中创建结构体struct socket
2) 用户空间中创建地址结构体struct sockaddr_in
3) 往地址结构体中加入ip和port并要将其转成网络字节序
(将对方的ip(inet_ntop函数)和port(ntohs函数)从网络字节序转换成本地字节序)
4) 将struct socket和struct sockaddr_in进行绑定(bind)
5) 监听来自客户端的连接请求(listen)
6) 从排队的队列中获得客户端的连接并对其服务(accept)
7) 通过socket发送和接受数据(write and read)
8) 释放资源(close)

绑定地址
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t len);
返回:成功返回0,出错-1

查找绑定到套接字的地址
#include <sys/socket.h>
int getsockname(int sockfd, struct sockaddr* restrict addr, socklen_t *restrict alenp);
返回:成功返回0,出错返回-1

获取对方地址
#include <sys/socket.h>
int getpeername(int sockfd, struct sockaddr* restrict addr, socketlen_t *restrict alenp);
返回:成功返回0,出错返回-1








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洪流之源

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值