第2关:socket编程

news2024/12/28 4:43:02

第2关:socket编程

  • 任务描述
  • 相关知识
    • 1、Socket
    • 2、socket函数
    • 3、bind函数
    • 4、listen、connetct函数
    • 5、accept函数
    • 6、read、write函数
    • 7、close、shutdown函数
    • 8、三次握手
    • 9、数据传输
    • 10、四次挥手
  • 编程要求及注意事项
  • 测试说明
  • 参考代码

任务描述

本关任务:
编写两个程序实现客户端与服务端的通信,clinet.c为客户端,server.c为服务器端。服务器端能够读取客户端发送的信息。

相关知识

为了完成本关任务,你需要掌握:1.socket编程,2.数据通信过程。

1、Socket

  网络中进程可以通过socket通信,socket起源于Unix,满足“一切皆文件”原理,即操作为“打开open->读写write/read->关闭close”。
  ①socket的调用函数主要有:

    socket()/*创建描述符,设定协议域和socket类型*/
    bind()/*绑定地址*/
    listen()/*监听*/
    connect()/*连接*/
    read()/*I/O读操作*/
    write()/*I/O写操作*/
    close()/*断开连接*/
    shutdown()/*部分断连*/

 ②socket操作主要有三类:
 1)三次握手:让客户端与服务端双方都能明确自己和对方的收、发能力是正常的。
 2)数据传输:socket使用的是TCP连接,为双向传输的对等模式,双方都可以同时向对方发送或接收数据。
 3)四次挥手:由于TCP连接是全双工,每个方向都必须单独进行关闭。

2、socket函数

int socket(int domain,int type,int protocol)
sockfd=socket();
    socket()创建一个socket描述符,标识唯一一个socket
    domain:协议域->AF_INET、AF_INET6、AF_LOCAL(AF_UNIX)、AF_ROUTE。协议族决定socket地址类型,通信中必须采用对应的地址,AF_INET决定要用ipv4地址(32位)与端口号(16位)组合看,AF_UNIX决定用一个绝对路径作为地址。
    type:socket->指定socket类型。常用SOCK_STREAM(TCP)、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET、SOCK_DGRAM(UDP)等
    protocol:协议->常用协议IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等,分别对应TCP传输、UDP传输、STCP传输、TIPC传输

注:type和protocol不可用随意组合,SOCKET_STREAM和IPPROTO_UDP不可用组合。当protocol为0,会自动选择type类型对应默认协议。
  socket函数创建一个socket时,返回的socket描述符存在于协议族address family中,没有具体地址,赋值一个地址必须调用bind()或者调用connect()、listen()系统自动随机分配端口。

3、bind函数

 bind()函数把一个地址族中特定地址赋值给socket,AF_INET、AF_INET6就是一个ipv4或ipv6地址和端口号组合,赋值给socket。

int bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen);
    sockfd:socket描述符,通过socket()创建,唯一标识一个socket。bind()将这个描述符绑定一个名字。
    addr:const struct sockaddr*指针,指向sockfd的协议地址。地址结构根据创建socket时的地址协议族不同而变化。
    addrlen:地址长度

注:①服务器启动时会绑定地址(ip+端口号)。提供服务时,服务端通过地址连接服务器。客户端不用绑定,系统自动分配端口号和自身iP地址组合。所以通常服务端listen前会调用bind(),客户端不会调用,在connect()时系统随机生成一个。
  ②主机字节序(大端小端模式):不同CPU有不同字节序类型,这些字节序指整数在内存中保存的顺序。
  1)little-endian,低位字节放内存低地址段,高位字节排放内存高地址端。
   2)big-endian,高位字节放内存低地址段,低位字节放内存高地址端。
  网络字节序:4个字节的32bit值以下次序传输,0-7、8-15、16-23、24-31。大端字节序。由于TCP/IP首部中所有二进制整数在网络中传输时都要求以这种次序,因此又称作网络字节序。字节序,发育一个字节类型数据在内存中存放顺序,一个字节的数据没有顺序问题。
  在绑定地址到socket时候,必须将主机字节序转换成网络字节序,不能让主机字节序跟网络字节序一样使用big-endian。

4、listen、connetct函数

 服务器调用socket()、bind()后就会调用listen()监听socket,如果客户端这时候调用connect()发出连接请求,服务器就会接受这个请求。

int listen(int sockfd,int backlog);
int connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen);
    listen中sockfd为要监听的socket描述符,backlog为相应socket可以排队的最大连接个数。
    socket()函数创建的socket是一个主动类型,listen()将socket变为被动类型等待客户连接请求。
    connect中sockfd为客户端socket描述符,addr为服务器socket地址,addrlen为socket地址长度。客户端调用connect函数建立与TCP服务器的连接。

5、accept函数

 TCP服务器调用socket()、bind()、listen()后,监听socket地址。TCP客户端调用socket()、connect()后,给TCP服务器发送一个连接请求。TCP服务器监听到请求,调用accept()接收请求,连接建立好开始I/O操作。

int accept(int sockfd,struct sockaddr *addr,socklen_t addrlen)
    sockfd服务器socket描述符
    addr返回客户端协议地址
    addrlen协议地址长度

 accept成功,返回值由内核自动生成的全新描述符,表示已与返回客户的TCP连接。
注:sockfd是服务器的socket描述符,服务器开始调用socket()生成的,即监听socket描述符,accept返回的是已连接socket描述符,一个服务器通常只创建一个监听socket描述符,在服务器生命周期内会一直存在,内核为每个服务器进程接收的客户连接创建一个已连接socket描述符,当服务器完成客户服务,相应已连接socket描述符会被关闭。

6、read、write函数

 服务器与客户建立好连接,调用网络I/O进行读写操作,网络中不同进程之间通信。

网络I/O操作
    read()/write()
    recv()/send()
    readv()/writev()
    recvmsg()/sendmsg()
    recvfrom/sendto()

7、close、shutdown函数

 服务器与客户端建立连接后,读写操作完,需要关闭相应的socket描述符。

#include<unistd.h>
int close(int fd);

 sockfd不能在作为read或者write的第一个参数。
注:close操作只是将相应的sockfd描述字引用计数-1,只有当引用计数为0的时候,才会触发TCP客户端向服务器发送终止连接请求。

 shutdown()函数,可以关闭socket一端或者全部。

int shutdown(int _fd,int _how)
    TCP连接是双向的(可读可写),使用close读写通道都关闭,使用shutdown有三种:
    ①howto=0,关闭读通道,可以继续写。
    ②howto=1,关闭写通道,只可以读。
    ③howto=2,关闭读写通道,和close一样,全部关闭。

8、三次握手

tcp建立连接进行“三次握手”:
①客户端向服务器发送一个SYN x。
②服务器向客户端发送一个SYN y,并对SYN x进行ACK x+1。
③客户端再向服务器发一个ACK y+1。
,

 ①客户端调用connect触发连接请求,向服务器发送SYN x包,connect进入阻塞状态;
 ②服务器listen监听到连接请求(收到SYN x),调用accept接受请求,向客户端发送SYN y和ACK x+1,accept进入阻塞状态;
 ③客户端收到服务器的SYN y和ACK x+1,对SYN y确认,connect返回ACK y+1;
 ④服务器收到ACK y+1,accept返回,三次握手完毕,连接建立。
注:客户端的connect在三次握手的第二次握手返回,服务端的accept在三次握手的第三次握手返回。

9、数据传输

,

①建立完连接后,进行数据传输,read和write。
②客户端发起给服务端写入,并发送SYN x+1和ACK y+1给服务端(xy未发生变化)。
③服务端发起给客户端读取,并发送ACK x+2。

10、四次挥手

,

①客户端应用进程调用close主动关闭连接,客户端TCP发送FIN x+2和ACK y+1。
②服务端接受到FIN x+2,执行被动关闭,对FIN确认。即当服务端收到FIN后停止数据的操作并发出一个ACK x+3客户端表示数据操作结束。
③一段时间后,服务端应用接收到文件结束符的应用进程调用close关闭服务端socket,发送一个FIN。(表示socket已经关闭)
④客户端接收到FIN,关闭客户端的socket,发送ACK y+2高速服务端。

编程要求及注意事项

根据client.c代码及提示,在右侧编辑器中选中server.c注释处补充代码。

测试说明

平台会对你编写的代码进行测试,比对输出结果。


开始你的任务吧,祝你成功!

参考代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define MAXLINE 4096

int main(int argc, char *argv[])
{
    int sockfd, n;                             // sockfd是客户端创建的socket描述字,客户端不需要区分监听listenfd和连接connfd。n为发送长度
    char recvline[MAXLINE], sendline[MAXLINE]; // recvline暂时没用,sendline为即将发送的数据
    struct sockaddr_in servaddr;               //创建需要连接的服务端地址

    if (argc != 2)
    {
        printf("usage: ./client <ipaddress>");
        exit(0);
    } //设置运行时候需要输入的格式,执行文件+服务端ip地址

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("create socket error:%s(errno:%d)\n", strerror(errno), errno);
        exit(0);
    } //创建socket描述字,因为客户端,只需要一次连接

    memset(&servaddr, 0, sizeof(servaddr)); //先把当前连接的服务端地址全填充0
    servaddr.sin_family = AF_INET;          //目的服务端地址协议簇为ipv4
    servaddr.sin_port = htons(6666);        //设置端口号6666
    if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
    {
        printf("inet_pton error for %s\n", argv[1]);
        exit(0);
    } //将目的服务端的地址,转换成网络地址,必须转换成网络地址!!argv[0]是./client,argv[1]是服务端的地址

    if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
    {
        printf("connect socket error:%s(errno:%d)\n", strerror(errno), errno);
        exit(0);
    } //创建连接,本机的socket通过服务端地址连接服务端,强转指针格式

    printf("send msg to server:\n"); //连接上后输出发送信息到服务端
    fgets(sendline, 4096, stdin);    //标准输入流中获取需要发送的信息,存储到sendline字符数组中
    if (send(sockfd, sendline, strlen(sendline), 0) < 0)
    {
        printf("send msg error:%s(errno:%d)\n", strerror(errno), errno);
        exit(0);
    }              //发送信息,sendline buff中的信息
    close(sockfd); //信息发送完关闭自己的sockfd,第一次挥手
    exit(0);
}

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

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

相关文章

轻松掌握,板对板连接器选型指南

一、什么是板对板连接器&#xff1f; 板对板连接器(简称BTB)&#xff0c;是精密电路中电源和信号耦合连接必不可少的器件。随着产品复杂度和电路设计规模的不断提升&#xff0c;板对板连接器也沿着市场需求向着高速率&#xff0c;高功率密度&#xff0c;轻薄化几个方向发展。 …

chatgpt赋能python:为什么Python不适合做SEO?——解析

为什么Python不适合做SEO&#xff1f;——解析 Python作为一种非常方便的编程语言&#xff0c;在数据处理、人工智能等方面有着广泛的应用。然而&#xff0c;在SEO领域&#xff0c;Python似乎并不受欢迎。本文将从Python不适用于SEO的几个方面做出详细的介绍&#xff0c;并为读…

WPF .Net6中使用Prism

.NET 6 是微软长期支持&#xff0c;并在移动、桌面、IoT 和云应用之间统一了 SDK、基础库和运行时。 Prism为程序设计提供指导,旨在帮助用户更加容易的设计和构建丰富、灵活、易于维护WPF桌面应用程序。Prism使用设计模式&#xff08;如MVVM,复合视图,事件聚合器&#xff09;…

02 【el和data的两种写法 MVVM模型】

02 【el和data的两种写法 MVVM模型】 1.el和data的两种写法 el有2种写法 创建Vue实例对象的时候配置el属性 先创建Vue实例&#xff0c;随后再通过vm.$mount(‘#root’)指定el的值 data有2种写法 对象式&#xff1a;data&#xff1a; { }函数式&#xff1a;data() { retur…

国产给力啊啊啊----国产MCU-CW32F030开发学习

国产MCU-CW32F030开发学习 1. 相关资料下载 1.1 武汉芯源半导体 武汉芯源半导体官网 武汉芯源半导体 武汉芯源 21ic 电子论坛 21ic 电子论坛 1.2 CW32F030系列资料 CW32F030技术文档 • 内核&#xff1a;ARM Cortex-M0 – 最高主频64MHz • 工作温度&#xff1a;-40℃ 至…

Java Number Math character类

文章目录 一、Java Number& Math 类1、Java Math 类2、Number & Math 类方法3、Math 的 floor,round 和 ceil 方法实例比较 二、Java Character 类1、转义序列2、character 方法 总结 一、Java Number& Math 类 一般地&#xff0c;当需要使用数字的时候&#xff0…

掌握海外新闻发布技巧,媒介易助你在全球获得曝光

​海外新闻稿发布平台是企业在拓展海外市场、增加品牌曝光度和提升知名度方面非常重要的工具。本文将介绍海外新闻稿发布平台的作用和建议&#xff0c;并提供一些建议&#xff0c;帮助企业更好地利用海外新闻稿发布平台进行营销推广。 一、海外新闻稿发布平台的作用 海外新闻稿…

chatgpt赋能python:Python人脸验证:简介与应用

Python人脸验证&#xff1a;简介与应用 Python作为一种强大的脚本语言&#xff0c;正变得越来越流行。它是一种易于学习和使用的语言&#xff0c;不仅在科学计算领域有很大的用武之地&#xff0c;而且在机器学习和人工智能领域也变得越来越流行。本文将重点介绍Python在人脸验…

通过 Gorilla 入门机器学习

机器学习是一种人工智能领域的技术和方法&#xff0c;旨在让计算机系统能够从数据中学习和改进&#xff0c;而无需显式地进行编程。它涉及构建和训练模型&#xff0c;使其能够自动从数据中提取规律、进行预测或做出决策。 我对于机器学习这方面的了解可以说是一片空白&#xf…

电商API分享:获取淘宝商品历史价格api调用示例 参数说明

在网络购物中&#xff0c;TAO宝是相信许多人的首选平台之一&#xff0c;而对于一个谨慎的购物者来说&#xff0c;价格的变化是非常重要的。所以获取淘宝商品历史价格&#xff0c;可以帮助购物者更好地作出决策&#xff0c;实现理性消费。获取淘宝商品历史价格主要能帮助到我们做…

PLC信号发生器(SCL+梯形图)

信号发生器的应用请参看下面的博客文章,在演示滤波器的作用时,我们可能也会用到信号的叠加等。 博途PLC滤波指令 Filter_PT1、Filter_PT2、Filter_DT1详细使用说明(含Simulink+博途PLC仿真)_RXXW_Dor的博客-CSDN博客博途S7-1200/1500PLC的PID控制和详细使用说明,请参看下…

自定义ViewGroup实现流式布局

目录 1、View的绘制流程 2、自定义ViewGroup构造函数的作用 3、onMeasure 方法 3.1、View的度量方式 3.2、onMeasure方法参数的介绍 3.3、自定义ViewGroup onMeasure 方法的实现 4、onLayout方法 5、onDraw方法 6、自定义View的生命周期 7、自定义流式布局的实现 扩展&#xff…

使用VBA在单元格中快速插入Unicode符号

Unicode 符号 Unicode 符号在实际工作中有着广泛的应用&#xff0c;比如用于制作邮件签名、文章排版、演示文稿制作等等。在 Excel 表格中&#xff0c;插入符号可以让表格的排版更加美观&#xff0c;同时也能够帮助用户更清晰地表达意思。 Dingbats Dingbats是一个包含装饰符…

龙蜥白皮书精选:开源 RISC-V 技术支持软硬件全栈平台

文/RISC-V ARCH SIG 01 背景介绍 RISC-V 是一套开源指令集为拥抱更加开放的芯片生态&#xff0c;指令集标准和扩展标准采用全球共享共治的模式&#xff0c;于 Arm 和 x86 有很大不同&#xff0c;因此也受到了业内人士的普遍关注&#xff0c;再未来有着很大应用潜力。龙蜥社区…

奇富科技语音论文入选国际顶会INTERSPEECH 2023

近日&#xff0c;奇富科技机器人团队论文《Eden-TTS&#xff1a;一种简单高效的非自回归“端到端可微分”神经网络的语音合成架构》&#xff08;Eden-TTS: A Simple and Efficient Parallel Text-to-speech Architecture with Collaborative Duration-alignment Learning&#…

【LeetCode】HOT 100(3)

题单介绍&#xff1a; 精选 100 道力扣&#xff08;LeetCode&#xff09;上最热门的题目&#xff0c;适合初识算法与数据结构的新手和想要在短时间内高效提升的人&#xff0c;熟练掌握这 100 道题&#xff0c;你就已经具备了在代码世界通行的基本能力。 目录 题单介绍&#…

1.Hive系列之简介

1. Hive简介 1.1 Hive是什么 Hive是一个基于Hadoop的数据仓库工具&#xff0c;它提供了类似于SQL的查询语言HiveQL&#xff0c;以及用于将查询转换为MapReduce任务的引擎。Hive的主要目的是使数据分析师和开发人员能够轻松地查询和分析存储在Hadoop集群中的数据&#xff0c;而…

如果我们使用大字符串作为 MySQL 索引键会发生什么

背景 正如我之前的文章里所解释的那样&#xff0c;B树的深度决定了MySQL在仅考虑使用索引的情况下的最坏查询性能。在SSD的帮助下&#xff0c;拥有一个比4层更深的B树应该是可以接受的。 那么下一个问题是&#xff1a;性能可能有多糟糕&#xff1f;在这里&#xff0c;我有意设…

elasticsearch中文分词使用以及疑问

最近用到elasticsearch作为知识库底层搜索引擎&#xff0c;开发反馈中文查询有问题&#xff0c;所以引用ik分词解决此问题。 一、安装 根据自己的版本找到github仓库下载&#xff0c;我此处使用为7.9.3版本 v7.9.3 Releases medcl/elasticsearch-analysis-ik GitHub 解压到…

git pull 和push讲解:016

pull 和push大致流程&#xff1a;(将远程仓库同步到本地仓库)>(在本地仓库修改并提交)>(推送修改内容到远程仓库) 1. 首先创建一个文件夹&#xff0c; 打开Git Bash终端&#xff0c; cd到这个文件夹内 2. 将(远程仓库)的克隆到这个文件夹内&#xff1a;git clone 远程仓库…