socket 基础

news2024/9/22 23:30:46

Socket是什么呢?

① Socket通常也称作“套接字”,用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过“套接字”向网络发出请求或者应答网络请求。

② Socket是连接运行在网络上的两个程序间的双向通信的端点。

③ 网络通讯其实指的就是Socket间的通讯。

④ 通讯的两端都有Socket,数据在两个Socket之间通过IO来进行传输。

或者更通俗的解释: socket = ip + port

Socket原理?

基于tcp连接的socket 连接图
在这里插入图片描述
在这里插入图片描述

流式传输:“客户端”,
1.socket()函数;
2.bind()函数可有可无,加上指定传输端口,不加随机分配端口;
3.connect()函数,填写服务端的地址与端口【网络间通信AF_STREAM】或者路径【进程间通信AF_DGRAM】;
4.send()函数;
5.recv()函数。

流式传输:“服务端”,
1.socket()函数;
2.bind()函数,必须加上指定传输端口【网络间通信AF_STREAM】或者是路径【进程间通信AF_DGRAM】;
3.listen()函数,使用isockfd;
5.accepc()函数,生成新的fd,inewfd;
6.send()函数,inewfd;
7.recv()函数,inewfd。

socket 接口函数

#include<sys/socket.h>

//socket 函数
int socket(int domain, int type, int protocol)

    第一个参数domain指明了协议族,通常用AF_INET、AF_INET6、AF_LOCAL等。AF表示地址族,选择 AF_INET 的目的就是使用 IPv4 进行通信。因为 IPv4 使用 32 位地址,相比 IPv6 的 128 位来说,计算更快,便于用于局域网通信。
    第二个参数type是Socket类型,常用的Socket类型我们之前已经介绍过了分别是SOCK_STREAM和SOCK_DGRAM因为我们要写的是TCP Socket编程所以我们使用SOCK_STREAM。
    第三个参数protocol表示传输协议一般取为0。因为一般情况下有了 domain和 type 两个参数就可以创建套接字了,操作系统会自动推演出协议类型,除非遇到这样的情况:有两种不同的协议支持同一种地址类型和数据传输类型。如果我们不指明使用哪种协议,操作系统是没办法自动推演的。
    
    example:
    int sockfd = socket(AF_INET, SOCK_STREAM, 0); //建立套接字,基于TCP
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0); //基于UDP
/=====================================================================/

//bind  函数  
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 
    
    第一个参数sockfd为上一步创建socket时的返回值。
    第二个参数addr 为 sockaddr 结构体变量的指针。该类型的定义原型如下:

    struct sockaddr_in {
        short   sin_family;    //协议族,与前面Socket函数中提到的一样,我们这里使用AF_INET
        u_short sin_port;        //端口号,需要
        struct in_addr sin_addr;    //IP地址,需要使用网络序
        char    sin_zero[8];    //没有实际意义,只是为了跟SOCKADDR结构在内存中对齐
    };
    第三个参数addrlen为addr 变量的大小,可由 sizeof() 计算得出。
    
    example:
    struct sockaddr_in serv_addr;    //创建结构体变量
    servaddr.sin_family=AF_INET;    //sin_family指代协议族和前面讲述socket()的第一个参数的含义相同,取值也需跟socke函数第一个参数值一样。
    servaddr.sin_port=htons(2000);    //sin_port存储端口号(使用网络字节顺序,对于htons()函数我们还有单独一章的说明,2000这个端口转换为网络字节序列。
    //理论上端口号的取值范围为是0到65536,但0到1023的端口一般由系统分配给特定的服务程序,比如Web 服务的端口号为 80所以我们的程序要尽量在 1024~65536 之间分配端口号。
 
    servaddr.sin_addr.s_addr=inet_addr("127.0.0.1");    //将iP地址127.0.0.1也就是本机地址转换为十进制
    bind(sockfd,(sockaddr*)&servaddr,sizeof(servaddr));    // 将套接字绑定到本地地址和端口上。
/=====================================================================/

//listen函数
int listen(int sockfd, int n);

    第一个参数为第一步sockfd创建socket时的返回值,套接字的描述符。
    第二个参数n用于指定接收队列的长度,也就是在Server程序调用accept函数之前最大允许进入的连接请求数,多余的连接请求将被拒绝,典型取值为5。

    example:
    listen(sockfd,5);//监听sockfd为创建套接字时的返回值。
/=====================================================================/
 
//accept函数        
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    
    sockfd为建立socket函数返回的值。
    addr为 sockaddr 结构体变量的指针,这个参数是指针类型,是向外传内容的,即addr将在函数调用后填入对方(客户端)的地址信息,如对方的IP、端口等。
    addrlen为 addr变量的大小,可由 sizeof() 计算得出。   
    
    example:
    struct sockaddr_in clientaddr//创建客户端地址结构体
    int aID;//用来接收accept函数返回值
    aID = accept(sockfd,(sockaddr*)&clientaddr, sizeof( clientaddr));//等待接收客户连接请求
/=====================================================================/
        
//connect函数 
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    sockfd:socket文件描述符
    addr:传出参数,返回链接客户端地址信息,含IP地址和端口号
    addrlen:传入传出参数(值-结果),传入sizeof(addr)大小,函数返回时返回真正接收到地址结构体的大小
    
    example:
    struct sockaddr_in server_addr;
    int cfd = socket(AF_INET, SOCK_STREAM, 0);
    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    inet_pton(AF_INET, CLIENT_IP, &server_addr.sin_addr.s_addr);
    server_addr.sin_port = htons(6666);
    connect(cfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
/=====================================================================/
        
//recv函数(tcp) & recvfrom( 通常用于UDP)
int recv (int fd, void *buf, int n, int flags);
    
    第一个参数fd,表示连接成功的套接字描述符。
    注意:这一步对于服务端而言是上一步accept的返回值;对于客户端而言是connect的返回值,并非是第一步socket创建套接字的返回值,不要搞混!
    第二个参数buf,就是为要接收的数据所在的缓冲区地址,也就是一个空的字符数组的首地址,这里放结果。
    第三个参数len为要接收数据的字节数。
    第四个参数flags为发送数据时的附带标记 ,一般情况下设置为0。但可以选择下列设置:
    MSG_DONTROUTE:表示不使用指定路由,对send、sendto有效
    MSG_PEEK:对recv, recvfrom有效,表示读出网络数据后不清除已读的数据
    MSG_OOB:对发送接收都有效,表示发送或接受加急数据
    
    example:
    char recBuf[200];//定义一个字符串用来保存客户端发来的数据
    recv(fd,recBuf,200,0);//接收来自客户端或服务端的数据
    recv缺省是阻塞函数,直到收到信息或出错才会返回
/=====================================================================/
        
//send函数(tcp) & sendto(通常用于UDP)
int send (int fd, const void *buf, int n, int flags);
    
    第一个参数fd,表示连接成功的套接字描述符。
    注意:这一步对于服务端而言是上一步accept的返回值;对于客户端而言是connect的返回值,并非是第一步socket创建套接字的返回值,不要搞混!
    第二个参数buf为要发送的数据所在的缓冲区地址,即一个已经存好内容的字符数组
    第三个参数len为要发送的数据的实际字节数+1。
    第四个参数flags为发送数据时的附带标记 ,一般情况下设置为0。但可以选择下列设置:
    MSG_DONTROUTE:表示不使用指定路由,对send、sendto有效 
    MSG_PEEK:对recv, recvfrom有效,表示读出网络数据后不清除已读的数据 
    MSG_OOB:对发送接收都有效,表示发送或接受加急数据
    
    example:
    char sendBuf[200];//定义一个数组用来保存发送的数据
    send(fd,sendBuf,strlen(sendBuf)+1,0);//用来发送服务端或客户端的数据
    与recv同样,send函数缺省也是阻塞函数,直到发送完毕或出错才会返回。
    需要注意,如果函数返回值与参数len不相等,则剩余未发送的信息需要再次发送
    
/=====================================================================/
        
//close函数 && shutdown函数 
int close (int fd);
int shutdown (int fd, int how)    
     /* how determines what to shut down:
     SHUT_RD   = No more receptions;
     SHUT_WR   = No more transmissions;
     SHUT_RDWR = No more receptions or transmissions.*/
        
/=====================================================================/    

socket 类似tcp 的工作原理

在这里插入图片描述
在这里插入图片描述

基于TCP(面向连接)的socket编程——流式套接字(SOCK_STREAM)

server.c
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>

#define PORT 23		//端口号
#define BACKLOG 5	//最大监听数

int main()
{
    int iSocketFD = 0;  //socket句柄
    int iRecvLen = 0;   //接收成功后的返回值
    int new_fd = 0; 	//建立连接后的句柄
    char buf[4096] = {0}; //
    struct sockaddr_in stLocalAddr = {0}; //本地地址信息结构图,下面有具体的属性赋值
    struct sockaddr_in stRemoteAddr = {0}; //对方地址信息
    socklen_t socklen = 0;
    
    //建立socket
    iSocketFD = socket(AF_INET, SOCK_STREAM, 0); 
    if(0 > iSocketFD)
    {
        printf("创建socket失败!\n");
        return 0;
    }	
    
    stLocalAddr.sin_family = AF_INET;  /*该属性表示接收本机或其他机器传输*/
    stLocalAddr.sin_port = htons(PORT); /*端口号*/
    stLocalAddr.sin_addr.s_addr=htonl(INADDR_ANY); /*IP,括号内容表示本机IP*/
    
    //绑定地址结构体和socket
    if(0 > bind(iSocketFD, (void *)&stLocalAddr, sizeof(stLocalAddr)))
    {
        printf("绑定失败!\n");
        return 0;
    }
    
    //开启监听 ,第二个参数是最大监听数
    if(0 > listen(iSocketFD, BACKLOG))
    {
        printf("监听失败!\n");
        return 0;
    }
    
    printf("iSocketFD: %d\n", iSocketFD);	
    //在这里阻塞知道接收到消息,参数分别是socket句柄,接收到的地址信息以及大小 
    new_fd = accept(iSocketFD, (void *)&stRemoteAddr, &socklen);
    if(0 > new_fd)
    {
        printf("接收失败!\n");
        return 0;
    }else{
        printf("接收成功!\n");
        //发送内容,参数分别是连接句柄,内容,大小,其他信息(设为0即可) 
        send(new_fd, "这是服务器接收成功后发回的信息!", sizeof("这是服务器接收成功后发回的信息!"), 0);
    }
    
    printf("new_fd: %d\n", new_fd);	
    iRecvLen = recv(new_fd, buf, sizeof(buf), 0);	
    if(0 >= iRecvLen)    //对端关闭连接 返回0
    {	
        printf("接收失败或者对端关闭连接!\n");
    }else{
        printf("buf: %s\n", buf);
    }
    
    close(new_fd);
    close(iSocketFD);
    
    return 0;
}
client.c
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
 
#define PORT 23			//目标地址端口号
#define ADDR "192.168.1.230" //目标地址IP
 
int main()
{
    int iSocketFD = 0; //socket句柄
    unsigned int iRemoteAddr = 0;
    struct sockaddr_in stRemoteAddr = {0}; //对端,即目标地址信息
    socklen_t socklen = 0;  	
    char buf[4096] = {0}; //存储接收到的数据
    
    //建立socket
    iSocketFD = socket(AF_INET, SOCK_STREAM, 0); 
    if(0 > iSocketFD)
    {
        printf("创建socket失败!\n");
        return 0;
    }	
    //绑定服务器的ip地址和端口
    stRemoteAddr.sin_family = AF_INET;
    stRemoteAddr.sin_port = htons(PORT);
    inet_pton(AF_INET, ADDR, &iRemoteAddr);
    stRemoteAddr.sin_addr.s_addr=iRemoteAddr;
    
    //connet()连接方法: 传入句柄,目标地址,和大小
    if(0 > connect(iSocketFD, (void *)&stRemoteAddr, sizeof(stRemoteAddr)))
    {
        printf("连接失败!\n");
        //printf("connect failed:%d",errno);//失败时也可打印errno
    }else{
        printf("连接成功!\n");
        recv(iSocketFD, buf, sizeof(buf), 0);//将接收数据打入buf,参数分别是句柄,储存处,最大长度,其他信息(设为0即可)。 
        printf("Received:%s\n", buf);
    }
    
    close(iSocketFD);//关闭socket	
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/818620.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1.1.2 SpringCloud 版本问题

目录 版本标识 版本类型 查看对应版本 版本兼容的权威——官网&#xff1a; 具体的版本匹配支持信息可以查看 总结 在将Spring Cloud集成到Spring Boot项目中时&#xff0c;确保选择正确的Spring Cloud版本和兼容性是非常重要的。由于Spring Cloud存在多个版本&#xff0c;因此…

Vulnhub: shenron: 3靶机

kali&#xff1a;192.168.111.111 靶机&#xff1a;192.168.111.171 信息收集 端口扫描 nmap -A -sC -v -sV -T5 -p- --scripthttp-enum 192.168.111.171 修改hosts后访问目标80端口&#xff0c;发现是wordpress wpscan收集目标用户&#xff0c;爆破出密码&#xff1a;ilov…

台灯头灯手电筒UL153亚马逊美国站测试要求

在将台灯、头灯或手电筒上架到亚马逊美国站之前&#xff0c;UL153测试是必不可少的一项认证。UL153是美国安全实验室&#xff08;Underwriters Laboratories&#xff09;颁布的一项标准&#xff0c;旨在确保产品的安全性和可靠性。那么&#xff0c;我们应该如何办理UL153测试报…

亚马逊调整数据存档政策:超两年的订单将从9月起存档!

2023年9月起&#xff0c;亚马逊美国站和欧洲站宣布对订单数据存档政策进行调整。该调整意味着自2023年9月起&#xff0c;所有历时两年以上的订单将按月存档。此举是为了确保客户的个人隐私和数据安全&#xff0c;存档订单将不再包含买家的个人身份信息&#xff0c;如姓名、电话…

git操作:修改本地的地址

Windows下git如何修改本地默认下载仓库地址 - 简书 (jianshu.com) 详细解释&#xff1a; 打开终端拉取git时&#xff0c;会默认在git安装的地方&#xff0c;也就是终端前面的地址。 需要将代码 拉取到D盘的话&#xff0c;现在D盘创建好需要安放代码的文件夹&#xff0c;然后…

Linux系统管理:虚拟机Rocky Linux安装

目录 一、理论 1.Rocky Linux 2.NetworkManager配置 3.ipaddress 配置文件 4.nmtui 配置 ipaddress 二、实验 1.虚拟机Rocky Linux安装准备阶段 2.安装Rocky Linux 3.进入系统 三、问题 1.网络配置文件权限不够 一、理论 1.Rocky Linux &#xff08;1&#xff0…

《2023数字化采购发展报告》发布,北京筑龙采购供应链数字化实践成功入选

近日&#xff0c;由亿邦智库联合中国物流采购与联合会公共采购分会共同编制的《2023数字化采购发展报告》&#xff08;下文称《报告》&#xff09;在第四届国有企业数智化采购与智慧供应链高峰论坛上重磅发布。作为一家服务30行业超大型及大中型国有企业的采购供应链数字化产品…

基于linux下的高并发服务器开发(第四章)- 多进程实现并发服务器(回射服务器)

1. socket // 套接字通信分两部分&#xff1a; - 服务器端&#xff1a;被动接受连接&#xff0c;一般不会主动发起连接 - 客户端&#xff1a;主动向服务器发起连接 2.字节序转换函数 当格式化的数据在两台使用不同字节序的主机之间直接传递时&#xff0c;接收端必然错误…

螺旋矩阵 II——力扣59

文章目录 题目描述法一 模拟 题目描述 法一 模拟 初始化一个二维向量&#xff0c;名为matrix&#xff0c;它有n行和n列。向量的每个元素都是一个整数&#xff0c;初始化为0。初始化二维向量的语法如下&#xff1a;vector<vector<int>> matrix(n, vector<int>…

unity 添加动画步骤

动画中不能有这俩组件会冲突 1.创建动画控制器 2.在需要做动画的节点添加动画组件 Animatr 3.把动画器拉到Animatr组件控制器中去 4.创建动画&#xff0c;把创建的动画推拽到动画器中。 5.点击绑定Animatr的节点把动画拖拽到动画播放器中。 6.点击动画可以调节速度 7. 配置参数…

Linux操作系统学习,Linux基础命令大全

目录 第一章、Linux简介和安装1.1&#xff09;Linux简介和分类1.2&#xff09;安装VMware虚拟机&#xff0c;在虚拟机中安装CentOS 7 第二章、虚拟机中Linux的IP地址配置详解2.1&#xff09;什么是IP地址&#xff0c;如何查看2.2&#xff09;虚拟机NAT模式中Linux的IP地址设置有…

上海亚商投顾:沪指冲高回落 两市成交重回万亿

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 市场情绪 三大指数今日冲高回落&#xff0c;盘初一度集体涨超1%&#xff0c;随后涨幅明显回落&#xff0c;上证50午后一度翻…

蓝桥杯2018省赛全球变暖dfs

全球变暖 问题描述格式输入格式输出样例输入样例输出评测用例规模与约定解析参考程序 问题描述 格式输入 格式输出 输出一个整数 样例输入 样例输出 1 评测用例规模与约定 最大运行时间&#xff1a;1s最大运行内存: 256M 解析 采用dfs的方式进行搜索&#xff0c;首先输入地…

python和java哪个更有前景,python和java哪个更有前途

大家好&#xff0c;小编为大家解答python和java哪个好学,零基础的问题。很多人还不知道python和java哪个更容易入门&#xff0c;现在让我们一起来看看吧&#xff01; 进入编程行业是很多人的梦想&#xff0c;现在越来越多的人都想要通过培训的方式进入IT行业中&#xff0c;但是…

Redis - 缓存的双写一致性

概念&#xff1a; 当修改了数据库的数据也要同时更新缓存的数据&#xff0c;缓存和数据库的数据要保持一致 那为什么会有不一致的情况呢&#xff1f; 如果不追求一致性&#xff0c;正常有两种做法 先修改数据库 后删除旧的缓存先删除旧的缓存 再修改数据库 我们以先删除旧的…

「教程」如何使用一套代码在多种程序中接入天气预警API

引言 天气预警的重要性不言而喻&#xff0c;在遭受自然灾害和极端天气时&#xff0c;及时获得预警信息可以拯救生命和减少财产损失。如今&#xff0c;随着科技的进步&#xff0c;开发者和企业可以借助天气预警 API 这款强大的服务&#xff0c;将实时预警信息集成到自己的应用中…

深刻理解python特性-列表推导式和生成器表达式

哈喽大家好&#xff0c;今天给大家介绍两个Python中特性-列表推导式和生成器表达式 今天我想向你介绍python语言的两个非常有用的特性&#xff1a;列表推导式和生成器表达式。这两个特性都可以让你用一行简洁的代码来创建一个序列&#xff0c;而不需要写循环或者函数。但是它们…

十年测试经验告诉你单元测试到底测什么

今天的前端夜点心我们来聊聊在项目中单元测试应该测些什么&#xff1f; 以国内互联网的开发节奏&#xff0c;在前端业务项目中全面覆盖单元测试有时显得不太可行&#xff0c;主要是因为以下这些绊脚石&#xff1a; UI 交互复杂&#xff0c;路径难以覆盖全面 工期紧&#xf…

HCIA云计算 V5.0题库

云计算&#xff0c;这是近几年听得最多词了&#xff0c;云计算对于网络的发展帮助非常大&#xff0c;它自身所产生的价值是不可估量的&#xff01;所以云计算的岗位对于很多IT公司来说&#xff0c;都是有一定地位的。华为认证云计算面向的对象很简单就是对云计算技术感兴趣的人…

明道云与美洽产品生态合作介绍

背景介绍 近来&#xff0c;B2B企业用人及获客成本居高不下的问题愈发显现&#xff0c;企业为提高核心竞争力&#xff0c;利用信息技术协调企业与客户在销售、营销和服务上的交互&#xff0c;在优化管理方式的同时&#xff0c;向客户提供个性化交互服务&#xff0c;以达到吸引新…