socket开发步骤及相关API介绍

news2024/11/23 3:38:10

socket服务器和客户端的开发步骤

TCP服务端:

  1. 创建套接字socket
  2. 为套接字添加信息(IP地址和端口号)bind
  3. 监听网络连接listen
  4. 监听到由客户端接入,接受一个连接accept
  5. 数据交互read、write
  6. 关闭套接字,断开连接close

TCP客户端:

  1. 创建套接字socket
  2. 知道IP地址端口号与服务端连接connect
  3. 数据交互read、write
  4. 关闭套接字,断开连接close

创建套接字socket

函数原型:

int socket(int domain,int type,int protocol)

参数:

1.domain:指明所使用的协议,通常为AF_INEF,表示互联网协议族(TCP/IP协议族)

  • AF_INET --- IPv4因特网域
  • AF_INET6 --- IPv6因特网域
  •  AF_UNIX --- Unix域
  • AF_ROUTE --- 路由套接字
  • AF_KEY --- 密钥套接字
  • AF_UNSPEC --- 未指定

2.type:指定socket的类型

  • SOCK_STREAM:流式套接字,面向连接的通信流,它使用TCP协议,从而保证了数据传输的正确性和顺序性。
  • SOCK_DGRAM:数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证是可靠、无差错的。它使用数据协议UDP。
  • SOCK_RAM:允许程序使用低层协议,原始套接字允许对底层协议如IP或ICMP进行直接访问,功能强大但使用较为不便,主要用于一些协议的开发。

3.protocol:通常赋值为0

  • 0选择type类型对应的默认协议
  • IPPROTO_TCP --- TCP传输协议
  • IPPROTO_UDP --- UDP传输协议
  • IPPROTO_SCTP --- SCTP传输协议
  • IPPROTO_TIPC --- TIPC传输协议

返回值:

成功返回socket套接字描述符,失败返回-1

套接字添加信息bind

用于绑定IP地址和端口号到socketfd

函数原型:

int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

参数:

  1. int sockfd:socket描述符
  2. const struct sockaddr *addr:是一个执行包含有本机IP地址及端口号等信息的socket类型的指针,指向要绑定给sockfd的协议地址结构,这个地址结构根据地址创建socket时的地址协议族的不同而不同。
  3. socklen_t addrlen:第二个参数结构体的长度

man手册给的第二个参数是:

但是一般写成如下形式,再强转为struct sockaddr *形式

例如如下写法:

监听网络连接listen

listen()的功能:

  • 设置能处理的最大连接数,listen()并未开始接受连线,只是设置socket的listen模式,listen函数只用于服务器端,服务器进程不知道要与谁连接,因此它不会主动的要求与某个进程连接,只是一直监听是否有其他客户进程与之链接,然后响应该连接请求,并对它做出处理,一个服务进程可以同时处理多个客户进程的连接。主要就两个功能:将一个未连接的套接字转换未一个被动套接字(监听),规定内核为套接字排队的最大连接数。
  • 内核为任何一个给监听套接字维护两个队列
  1. 未完成连接队列,每个这样的SYN报文段对应其中一项:已由某个客户端发出并到达服务器,而服务器正在等待完成响应的TCP三次握手过程,这些套接字处于SYN_REVD状态。
  2. 已完成连接队列。每个已完成TCP三次握手过程的客户端对应其中一项,这些套接字处于ESTABLISHED状态。

函数原型:

 int listen(int sockfd, int backlog);

参数:

  1. int sockfd:是socket系统调用返回的服务器端socket描述符
  2. int backlog:指定在请求队列中允许的最大请求数

返回值:

成功返回0,失败返回-1,并且errno中包含相应的错误码

客户端连接服务器connect

功能:

用于绑定之后的client端,与服务器建立连接

函数原型:

int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

参数:

  1. int sockfd:socket系统调用返回的服务器端socket描述符
  2. struct sockaddr *addr:用来返回已连接的对端(客户端)的协议地址
  3. socklen_t *addrlen:客户端地址的长度

返回

成功返回0,失败返回-1,并且errno中包含相应的错误码

接受连接accept

功能:

accept函数由TCP服务器调用,用于从已经完成连接队列队头返回下一个已完成连接,如果已完成连接队列为空,那么进程之间进入睡眠。

函数原型:

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

参数:

  1. int sockfd:socket系统调用返回的服务器端socket描述符
  2. struct sockaddr *addr:用来返回已连接的对端(客户端)的协议地址
  3. socklen_t *addrlen:客户端地址的长度

返回值:

该函数的返回值是一个新的套接字描述符,返回值是表示已连接的套接字描述符,而第一个参数是服务器监听套接字描述都,一个服务器通常仅仅创建一个监听套接字,它在服务器的生命周期内一直存在。内核为每个由服务器进程接受的客户端连接创建一个已连接套接字(表示TCP三次握手协议已完成),当服务器完成对某个给定客户的服务时,响应的已连接套接字就会被关闭。

数据交互read、write

与文件编程中使用的read、write是一模一样的,不过多赘述

此外还要另外两种数据收发API:

  1.  ssize_t send(int sockfd, const void *buf, size_t len, int flags);
  2. ssize_t recv(int sockfd, void *buf, size_t len, int flags);

其实和read、write也是差不多的,只不过多了一个flag参数,flag表示控制选项,一般设置为0。

字节序转换API

       #include <arpa/inet.h>

       uint32_t htonl(uint32_t hostlong);返回网络字节序的值

       uint16_t htons(uint16_t hostshort);返回网络字节序的值

       uint32_t ntohl(uint32_t netlong);返回主机字节序的值

       uint16_t ntohs(uint16_t netshort);返回主机字节序的值uint32_t

h代表host,n代表net,s代表short(两个字节),l代表long(四个字节),通过上面4个函数可以表示主机字节序和网络字节序之间的转换。有时可以用INADDR_ANY , INADDR_ANY指定地址让操作系统自己获取。

地址转换API

一般用下面黑体标出的两个

        #include <sys/socket.h>
       #include <netinet/in.h>
       #include <arpa/inet.h>

       int inet_aton(const char *cp, struct in_addr *inp);把字符串形式的192.168.1.123转为网络能识别的格式

       in_addr_t inet_addr(const char *cp);

       in_addr_t inet_network(const char *cp);

       char *inet_ntoa(struct in_addr in);把网络格式的ip地址转为字符串形式

       struct in_addr inet_makeaddr(int net, int host);

       in_addr_t inet_lnaof(struct in_addr in);

       in_addr_t inet_netof(struct in_addr in);

示例一:

服务端:连接客户端并读取客户端IP、发送的信息并返回读取状态。

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>

int main()
{
        int s_fd;
        char readBuf[128];
        memset(readBuf,0,sizeof(readBuf));
        int nread=0;
        struct sockaddr_in s_addr;
        struct sockaddr_in c_addr;

        memset(&s_addr,0,sizeof(struct aockaddr_in *));
        memset(&s_addr,0,sizeof(struct aockaddr_in *));

        s_fd=socket(AF_INET,SOCK_STREAM,0);

        if(s_fd==-1)
        {
                printf("creat soclet failed\n");
                perror("socket");
                exit(-1);
        }

        s_addr.sin_family=AF_INET;
        s_addr.sin_port=htons(9090);
        inet_aton("169.254.6.127",&(s_addr.sin_addr));

        bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));

        listen(s_fd,10);

        int clen=sizeof(struct sockaddr_in);
        int c_fd=accept(s_fd,(struct sockaddr *)&c_addr,&clen);

        if(c_fd == -1)
        {
                perror("acccept");
        }

        printf("get connect :%s\n",inet_ntoa(c_addr.sin_addr));

        nread=read(c_fd,readBuf,128);
        if(nread ==-1)
        {
                perror("read");
        }
        else if(nread>0)
        {
                printf("get message:%d,%s\n",nread,readBuf);
        }
        else
        {
                printf("client quit\n");
        }

         write(c_fd,"hhhhhhhhhhhhhhh",128);


        return 0;
}

示例二:

客户端:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
int main()
{

        int c_fd;
        char readBuf[128];
        memset(readBuf,0,sizeof(readBuf));
        int nread=0;
        struct sockaddr_in c_addr;

        memset(&c_addr,0,sizeof(struct aockaddr_in *));

        c_fd=socket(AF_INET,SOCK_STREAM,0);

        if(c_fd==-1)
        {
                printf("creat soclet failed\n");
                perror("socket");
                exit(-1);
        }
        c_addr.sin_family=AF_INET;
        c_addr.sin_port=htons(9090);
        inet_aton("169.254.6.127",&(c_addr.sin_addr));

        if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)) ==-1)

        {
                perror("connect");
                exit(-1);
        }


        write(c_fd,"xxxxxxxxx",128);

        nread=read(c_fd,readBuf,128);
        if(nread ==-1)
        {
                perror("read");
        }
        else
        {
                printf("get message from sever:%d,%s\n",nread,readBuf);
        }


        return 0;
}

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

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

相关文章

JAVA二叉搜索树(专门用来查找)

目录 二叉搜索树又叫二叉排序树&#xff0c;它具有以下特征 二次搜索树的效率 模拟最简二叉搜索树代码 代码片段分析 查找二叉搜索树数据&#xff1a; 如果我们用递归的方法查找数据有什么不一样? 插入数据 删除数据(难点) 二叉搜索树又叫二叉排序树&#xff0c;它具有以下特征…

python之pyQt5实例:几何绘图界面

使用PyQt5设计一个界面&#xff0c;其中点击不同的按钮可以在画布上画出点、直线、圆和样条曲线 from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton,QHBoxLayout,QVBoxLayout,QWidget,QLabel from PyQt5.QtGui import QPainter, QPen, QColor from PyQt5.Q…

nssm将exe应用封装成windows服务

一、简介 NSSM&#xff08;Non-Sucking Service Manager&#xff09;是一个用于在Windows操作系统上管理和运行应用程序作为服务的工具。它提供了一种简单的方法来将任意可执行文件转换为Windows服务&#xff0c;并提供了一些额外的功能和配置选项。 优点&#xff1a; 简单易…

【遍历二叉树算法描述】

文章目录 遍历二叉树算法描述先序遍历二叉树的操作定义中序遍历二叉树的操作定义后序遍历二叉树的操作定义 遍历二叉树算法描述 1.遍历定义&#xff1a;顺着某一条搜索路径寻访二叉树中的结点&#xff0c;使得每一个结点均被访问一次&#xff0c;而且仅访问一次&#xff08;又…

【算法-数组3】螺旋数组(一入循环深似海啊!)

今天&#xff0c;带来数组相关算法的讲解。文中不足错漏之处望请斧正&#xff01; 理论基础点这里 螺旋数组 1. 思路 这道题主要是模拟转圈过程&#xff0c;但是要处理的边界条件比较多&#xff0c;常见的问题就是每条边的处理都有自己的逻辑&#xff0c;那这就很难。如果不…

基于正负序双dq旋转坐标系锁相环 DDSRF-PLL模型

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; DDSRF-PLL则是通过构建数学解耦网络来消除&#xff12;倍电网频率的交流耦合分量 。由于DDSRF-PLL是在解耦多同步坐标系锁相环的基础上得到的&#xff0c;因此&#xff0c;需要研究解耦多同步坐标系锁相环的组…

高速串行总线—Rapid IO

SRIO简介 Rapid IO 是一种高性能、 低引脚数、 基于数据包交换的互连体系结构&#xff0c;是为满足和未来高性能嵌入式系统需求而设计的一种开放式互连技术标准。RapidIO主要应用于嵌入式系统内部互连&#xff0c;支持芯片到芯片、板到板间的通讯&#xff0c;可作为嵌入式设备的…

第26期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大型语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以…

Vue-router 路由的基本使用

Vue-router是一个Vue的插件库&#xff0c;专门用于实现SPA应用&#xff0c;也就是整个应用是一个完整的页面&#xff0c;点击页面上的导航不会跳转和刷新页面。 一、安装Vue-router npm i vue-router // Vue3安装4版本 npm i vue-router3 // Vue2安装3版本 二、引入…

什么是数据可视化,为什么数据可视化很重要?

数据可视化是数据的图形表示&#xff0c;可以帮助人们更轻松地理解和解释复杂的信息。它涉及创建数据的视觉表示&#xff0c;例如图表、图形、地图和其他视觉元素&#xff0c;以传达数据中的见解、模式和趋势。数据可视化是将原始数据转化为可操作知识的关键工具。 以下是数据…

CSS 背景、文本、字体

CSS背景&#xff1a; CSS背景属性用于定义HTML元素的背景。CSS属性定义背景效果&#xff1a;background-color&#xff1b;background-image&#xff1b;background-repeat&#xff1b;background-attachment&#xff1b;background-position。 background-color属性定义元素…

swift语言用哪种库适合做爬虫?

因为Swift语言并没有在语言层面上支持正则表达式&#xff0c;这对于爬虫来说是一个很大的缺陷。不过&#xff0c;Swift语言可以通过调用其他语言的库来实现爬虫功能&#xff0c;比如可以使用Python的BeautifulSoup库或者JavaScript的Cheerio库来解析HTML页面。但是相比于Python…

【Proteus仿真】【51单片机】汽车尾灯控制设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真51单片机控制器&#xff0c;使用按键、LED模块等。 主要功能&#xff1a; 系统运行后&#xff0c;系统运行后&#xff0c;系统开始运行&#xff0c;K1键控制左转向灯&#xff1b;…

第12章 PyTorch图像分割代码框架-2

模型模块 本书的第5-9章重点介绍了各种2D和3D的语义分割和实例分割网络模型&#xff0c;所以在模型模块中&#xff0c;我们需要做的事情就是将要实验的分割网络写在该目录下。有时候我们可能想尝试不同的分割网络结构&#xff0c;所以在该目录下可以存在多个想要实验的网络模型…

JVM虚拟机:垃圾回收器之Parallel Scavenge

本文重点 在前面的课程中,我们学习了新生代的串行化垃圾回收器Serial,本文我们将学习新生代的另外一个垃圾回收器Parallel Scavenge(PS),PS是一个并行化的垃圾回收器,它使用复制算法来清理新生代的垃圾。 运行方式 如上所示,当进行垃圾回收的时候,它会暂停工作线程,而…

第二章: 创建第一个Spring Boot 应用

第二章: 创建第一个Spring Boot 应用 前言 本章重点知识:构建你的第一个Spring Boot应用:以一个简单的例子来引导你进入Spring Boot的开发,包括如何使用Spring Initializr来创建项目,以及如何使用Maven或Gradle构建和运行项目等 IntelliJ IDEA 开发工具中安装 Spring Init…

网络原理---网络初识

文章目录 网络发展史独立模式网络互连局域网LAN广域网WAN 网络通信基础IP地址端口号 认识协议什么是协议&#xff1f;协议分层为什么要分层&#xff1f;两种典型的分层方式&#xff1a;OSI七层TCP/IP五层 网络发展史 从我们出生以来&#xff0c;网络世界就已经纷繁错杂。我们虽…

简单CMake入门

CMake可以生成不同平台下的Makefile&#xff0c;有了CMake不用再写复杂的Makefile 视频教程&#xff1a;CMake 6分钟入门&#xff0c;不用再写复杂的Makefile 先前知识 Makefile简单入门 Cmake特性 CMake是一个用于管理C/C项目的跨平台构建工具。 跨平台&#xff1a;CMake是…

CSS示例001:鼠标放div上,实现旋转、放大、移动等效果

GPT能够很好的应用到我们的代码开发中&#xff0c;能够提高开发速度。你可以利用其代码&#xff0c;做出一定的更改&#xff0c;然后实现效能。 css实战中&#xff0c;经常会看到这样的场景&#xff0c;鼠标放到一个图片或者一个div块状时候&#xff0c;会出现旋转、放大、移动…

webgoat-Insecure Deserialization不安全的序列化

A&#xff08;8&#xff09;不安全的反序列化 反序列化是将已序列化的数据还原回对象的过程。然而&#xff0c;如果反序列化是不安全的&#xff0c;那么恶意攻击者可以在序列化的数据中夹带恶意代码&#xff0c;从而在反序列化时执行这些代码。这种攻击被称为反序列化。 什么…