当前位置: 首页 > article >正文

Linux高阶——1116—SOCKET套接字基础

1、SOCKET套接字基础

操作系统提供,用于开发网络应用的一系列API函数,我们称之为套接字函数

套接字函数适用于各个语言和平台,除了API可以不同,其他概念理论或流程逻辑都相同

1、在Linux操作系统中,sock为整型,也称int sockfd,sock描述符,后续网络通信都是用此描述符

2、int sockfd,包含网络信息,默认下包含默认地址0.0.0.0与随机端口,因此sockfd创建后可以立即使用

3、int sockfd,套接字描述符,后续用于数据传输,recv(int sock),send(sockfd),sendto(sockfd),recvfrom(sockfd)

4、struct socksddr_in网络信息结构体

2、socket函数

1、socket()——socket创建

int sockfd=socket(AF_INET|AF_INET6,SOCK_STREAM|SOCK_DGRAM,0);

第一个参数——指定使用的socket协议

第二个参数——传输层协议,TCP或UDP

返回值——成功返回整型的(大于0的)socket,失败返回-1

当刚创建时,socket包含的ip为本机任意ip,包含的端口号为随机端口号,因此刚创建出来时就可以使用

因此客户端的sockfd创建以后,无需绑定,也可以使用,因为里面含有本机任意ip和端口号

2、bind()——socket绑定

int value=bind(int sockfd,struct sockaddr* addr,socklen_t addrlen);
bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));

第一个参数——int类型的socket

第二个参数——网络信息结构体的地址

第三个参数——网络信息结构体的长度

返回值——成功返回0,不成功返回-1

sockfd里可以自定义网络信息(指定ip和port),使用bind对int sockfd中的网络信息进行设置自定义

固定信息,一般只有服务端需要,大多数服务端必须绑定,保证客户端能够找到服务端,客户端随意

大多数时间udp都需要bind,而tcp只有服务端需要绑定

3、listen()——监听网络连接状态

listen(int sockfd,int backlog=128);

第一个参数——需要监听的socket

第二个参数——监听序列

返回值——成功返回0,不成功返回-1

监听连接状态,一般只有TCP协议使用

TCPIP协议的后台有双队列,第一个队列存储的为等待三次握手的socket,第二个队列存储握手成功的socket

等待三次握手的队列不能过短:因为如果等待握手的socket的数量超过了等待握手队列的长度,则下个将要等待连接的socket会被服务器主机将RST置0(复位:让客户端重连,如果客户端不重连,连接将会丢失)

队列不能过长:浪费内存资源

定位128的队列长度可以保证过万的连接

4、accept()——执行此函数等待连接,并完成握手(服务端使用)

如果存在一个服务端,有20000个客户端连接此服务端,此时服务器软件内存在多少个socket?

答:存在20001个,存在1个socket是专门用于请求连接的,其余20000个均为连接成功后,客户端的用于传输数据的socket

用于连接的socket

int socket_sock;

用于传输的socket——计算进程sock最大值,sock最大值=连接数量+1

int client_sock;

accept是经典的阻塞连接函数

client_sock=accept(server_sock,struct sockaddr* client_addr,&addrlen);

第一个参数——服务端socket

第二个参数——客户端连接成功,成功后将客户端的网络信息结构体传出到client_addr中,获得客户端的ip和端口号

第三个参数——传入传出信息长度,传入能够接收的长度,传出结构体实际接收到多大的长度

socklen_t addrlen;
addrlen=sizeof(client_addr);

需要注意:每次连接前都要初始化addrlen,否则能够输入的大小会越来越小

返回值——指向客户端的socket——client_sock

client_sock存储指向客户端的sock,后续与客户端数据通信使用它

5、connect()——通过此函数对目标请求tcp连接(客户端使用)

connect(int sockfd,struct sockaddr* destaddr,sizeof(destaddr));

第一个参数——连接的socket(客户端只有一个socket)

第二个参数——目标信息结构体

第三个参数——目标信息结构体的长度

阻塞请求连接,成功返回0,失败返回-1

6、recv()读取指定sockfd中的数据包

ssize_t wlen=send(int sockfd,void* buf,strlen(buf),MSG_NOSIGNAL);

第一个参数——发送目标的sockfd

第二个参数——数据buf

第三个参数——数据长度size

第四个参数——选项

返回值——发送的长度

7、send()向sockfd发送数据包

ssize_t rlen=recv(int sockfd,void* buf,size(buf),MSG_DONTWAIT);

第一个参数——发送的人的sockfd

第二个参数——数据buf

第三个参数——数据长度size

第四个参数——选项flags=0—阻塞读,MSG_DONTWAIT—非阻塞读

返回值——发送的长度

3、客户端代码

#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>

int main()
{
    struct sockaddr_in server_addr;
    bzero(&server_addr,sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);
    server_addr.sin_addr.s_addr = inet_addr("82.157.31.74");

    int client_sock;
    if((client_sock=socket(AF_INET,SOCK_STREAM,0))==-1)
    {   
        perror("sock create failed");
        return -1; 
    }   

    socklen_t addrlen;
    printf("TCP IO Client Running...\n");
    addrlen = sizeof(server_addr);
    if((connect(client_sock, (struct sockaddr*)&server_addr, addrlen))==-1)
    {   
        perror("failed");
        close(client_sock);
        return -1; 
    }   
    char buffer[1024];
    recv(client_sock, buffer, sizeof(buffer), 0); 
    printf("Received from server: %s\n", buffer);

    close(client_sock);
}

http://www.kler.cn/a/399190.html

相关文章:

  • Ubuntu 的 ROS 操作系统 turtlebot3 导航仿真
  • Element-ui Select选择器自定义搜索方法
  • springboot企业级项目常用的pom依赖
  • 风电电力系统低碳调度论文阅读第一期
  • docker-hub 无法访问,使用windows魔法拉取docker images再上传到linux docker环境中
  • 嵌入式硬件杂谈(二)-芯片输入接入0.1uf电容的本质(退耦电容)
  • 数据结构大致分类
  • 函数式组件和类组件的区别
  • WPF+MVVM案例实战、自定义控件和特效实现
  • 解析安卓镜像包和提取DTB文件的操作日志
  • Unity6 + Android Studio 开发环境搭建【备忘】
  • 机器学习实战笔记32-33:网格搜索原理、参数详解及代码实操
  • 关于性能测试:数据库的 SQL 性能优化实战
  • STL序列式容器之priority_queue
  • vue使用List.reduce实现统计
  • 前端开发设计模式——责任链模式
  • acwing算法基础03-递归,枚举
  • 【JavaScript】call、apply、bind
  • 数据结构中的抽象数据类型、逻辑结构、存储结构等到底是什么?
  • LeetCode 445.两数相加 II
  • 【不写for循环】玩玩行列
  • nfs服务器--RHCE
  • 论文学习(四) | 基于数据驱动的锂离子电池健康状态估计和剩余使用寿命预测
  • 后台运行docker compose项目,一直失败,提示:Timeout exceeded while awaiting headers?让我来看看~
  • idea 删除本地分支后,弹窗 delete tracked brank
  • 移门缓冲支架:减少噪音,提升生活质量