socket通信基础讲解及示例-C

socket通信之C篇

  • 服务端与客户端
    • 简介
  • socket通信
    • 服务端与客户端通信模型
    • 通信实战
      • server(服务端)创建
      • client(客户端)创建
  • 函数详解
    • 创建套接字 socket
    • 绑定端口bind
    • 进入监听状态listen
    • 获取客户端连接请求accept
    • 接收网络数据read
    • 发送数据write
    • 关闭套接字close
    • 连接指定服务端connect

服务端与客户端

简介

 服务端与客户端是计算机网络通信的两个主要角色,在物理上并没有什么区别,可以同时在一个设备,也可在不同的设备上。只不过在市场上,为了性能和更好的提供服务。大部分的服务端与客户端不在同个设备中。
客户端(client)一般指通过应用程序(例如手机app,电脑软件)或浏览器网页向服务器获取资源和数据的计算机或设备。
服务端(server)一般指提供服务的计算机或设备。服务端接收并处理客户端的请求,并返回对应的结果。
服务器指服务端所部署的计算机或设备

socket通信

以下均在linux系统中实现,socket通信是进程通信的一种方式。以下操作函数的头文件位于socket.h

服务端与客户端通信模型

在这里插入图片描述

通信实战

server(服务端)创建

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>


int main()
{

	int socketfd = socket(AF_INET, SOCK_STREAM, 0);
	if(socketfd < 0)
	{
		printf("creat socket error\n");
		return -1;
	}
	
	struct sockaddr_in socket_addr;
	memset(&socket_addr, 0, sizeof(socket_addr)); 
	 
	socket_addr.sin_family = AF_INET;
	socket_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	socket_addr.sin_port = htons(4017);
	
	if(bind(socketfd, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0)
	{
		printf("bind port error\n");
		return -1;
	}

	if(listen(socketfd, 5) < 0)
	{
		printf("listen error\n");
		return -1;
	}
	
	struct sockaddr_in client_addr;
	int clilen = sizeof(struct sockaddr_in);
	int clifd = accept(socketfd, (struct sockaddr*)&client_addr, (socklen_t*)&clilen);
	
	char buf[256] = {0};
	char sendbuf[] = "hello";
	while(1)
	{
		memset(buf, 0, 	sizeof(buf));
		read(clifd, buf, 255);
		printf("recv message is: %s\n", buf);
		write(clifd, sendbuf, 5);
		sleep(1);
	}
	
	close(clifd);
	close(socketfd);
	
	return 0;
}

client(客户端)创建

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


int main()
{

	int socketfd = socket(AF_INET, SOCK_STREAM, 0);
	if(socketfd < 0)
	{
		printf("creat socket error\n");
		return -1;
	}
	
	struct sockaddr_in socket_addr;
	memset(&socket_addr, 0, sizeof(socket_addr)); 
	 
	socket_addr.sin_family = AF_INET;
	socket_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
	socket_addr.sin_port = htons(4017);
	
	if(connect(socketfd, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0)
	{
		printf("bind port error\n");
		return -1;
	}

	char buf[256] = {0};
	char sendbuf[] = "client msg";
	while(1)
	{
		memset(buf, 0, 	sizeof(buf));
		read(socketfd, buf, 255);
		printf("recv message is: %s\n", buf);
		write(socketfd, sendbuf, 11);
		sleep(1);
	}
	
	close(socketfd);
	
	return 0;
}

函数详解

创建套接字 socket

  • 函数原型
int socket(int domain, int type, int protocol)
  • 函数解析
    作用 :用于创建一个指定协议的sockfd,即一个套接字。

例如创建一个tcp,ipv4的sockfd

int socketfd = socket(AF_INET, SOCK_STREAM, 0);

返回: 创建失败返回-1,成功返回文件描述符。

  • 参数解析
    以下枚举值只列出部分
参数说明枚举
domain指定通信域,即选择通信用的协议族AF_INET:ipv4
AF_INET6:ipv6
type指定套接字类型SOCK_STREAM:提供有序的、可靠的、双向的、基于连接的字节流,流式协议。
SOCK_DGRAM:固定长度的、无连接的、不可靠的报文传递,报式协议
protocol具体的一个协议一般写0
流式协议默认是TCP
报式协议默认是UDP

绑定端口bind

  • 函数原型
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • 函数解析
    作用 :将socket创建的socketfd与地址addr进行绑定。大部分用来绑定端口。一般在于服务端使用,如果客户端在需要绑定端口的情况下,也可以使用。

例如将刚刚创建的socketfd与本地端口4017进行绑定

struct sockaddr_in socket_addr;
memset(&socket_addr, 0, sizeof(socket_addr)); 
 
socket_addr.sin_family = AF_INET;
socket_addr.sin_addr.s_addr = htonl(INADDR_ANY);
socket_addr.sin_port = htons(4017);

bind(socketfd, (struct sockaddr *)&socket_addr, sizeof(socket_addr));

返回:成功返回0,一般端口被其他进程占用时,才会返回失败!

  • 参数解析
参数说明
sockfd创建的套接字
sockaddr地址,结构体中包含了协议族,端口号以及地址ip
socklen_t地址所指向的结构体的地址长度

进入监听状态listen

  • 函数原型
int listen(int sockfd, int backlog);
  • 函数解析
    作用 :让服务端进入监听状态,等待客户端的连接。用于服务端的进程。需在accept之前使用

例如 最大监听客户端数量为5

listen(socketfd, 5);

返回
成功返回0

  • 参数解析
参数说明
sockfd创建的套接字
backlog服务端等待连接的最大数量(即半连接和全连接最大之和)

获取客户端连接请求accept

  • 函数原型
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  • 函数解析
    作用 :获取客户端的连接请求并建立连接

例如

struct sockaddr_in client_addr;
int clilen = sizeof(struct sockaddr_in);

int clifd = accept(socketfd, (struct sockaddr*)&client_addr, (socklen_t*)&clilen);

返回:成功返回客户端的socketfd,后期通过该socketfd与此客户端进行通信。失败返回-1

  • 参数解析
参数说明
sockfd用于监听的文件描述符
addr用于返回监听到的客户端的地址信息
addrlenaddr的字节大小

接收网络数据read

  • 函数原型
ssize_t read(int fd, void *buf, size_t count);
  • 函数解析
    作用 :接收网络数据

例如获取从clientfd中接收到的网络数据

char buf[256] = {0};
read(clientfd, buf, 256);

返回:成功返回接收到的网络数据长度;失败返回<0。
头文件:unistd.h

  • 参数解析
参数说明
sockfd需要获取数据的对象socketfd
buf接收到的网络数据
count限制字节接收长度。
当缓冲区长度大于该长度时,返回count长度字节;
档缓冲区长度小于该长度时,返回实际长度的字节

发送数据write

  • 函数原型
ssize_t write(int fd, const void *buf, size_t count);
  • 函数解析
    作用 :用于发送数据

例如 :对clientfd发送abc

char sendbuf[] = “hello”;
write(clientfd, sendbuf, 3);

返回:成功返回成功写入的字节数,失败返回-1
头文件:unistd.h

  • 参数解析
参数说明
fd需要发送数据的对象socketfd
buf发送的数据
count当实际发送数据长度大于count时,按count数量字节数发送,否则按实际长度发送

读取和写入除了read和write外,还有recv和send;recvmsg和sendmsg等。

关闭套接字close

  • 函数原型
int close(int fd);
  • 函数解析
    作用 :关闭指定套接字

例如

close(clientfd);

返回:成功返回0

  • 参数解析
参数说明
fd需要关闭的套接字

连接指定服务端connect

  • 函数原型
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

注意 客户端使用

  • 函数解析
    作用 :在tcp中用于跟服务端建立连接,而在udp中仅仅是在本地对服务端的IP地址和端口与创建的sockfd进行绑定记录

例如 连接ip地址为127.0.0.1(本地回环),且端口号为4017的服务端进程

struct sockaddr_in socket_addr;
memset(&socket_addr, 0, sizeof(socket_addr)); 
 
socket_addr.sin_family = AF_INET;
socket_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
socket_addr.sin_port = htons(4017);

connect(sockfd, (struct sockaddr *)&socket_addr,sizeof(socket_addr));

返回:成功返回0,失败返回-1

inet_addr所在头文件为:arpa/inet.h

  • 参数解析
参数说明
sockfd用于通信的文件描述符
addr客户端所要连接的服务端的地址信息
addrlenaddr的内存大小

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

音素与视素(Viseme)

什么是视素&#xff08;视位&#xff09; 音素(Phoneme)&#xff0c;是人类语言中能够区别意义的最小声音单位。视素(Viseme)&#xff0c;是指与某一音素相对应的嘴、舌头、下腭等可视发音器官所处的状态。Viseme是MPEG-4 标准提出来的概念。 有时Viseme也翻译为视位。下面会…

JavaEE初阶Day 10:多线程(8)

目录 Day 10&#xff1a;多线程&#xff08;8&#xff09;单例模式阻塞队列1. 生产者消费者模型1.1 生产者消费者模型解耦合1.2 生产者消费者模型削峰填谷 2. 生产者消费者代码3. 阻塞队列实现 Day 10&#xff1a;多线程&#xff08;8&#xff09; 单例模式 单例模式&#xf…

springboot中mongodb连接池配置-源码分析

yml下spring.data.mongodb 以前mysql等在spring.xxx下配置&#xff0c;现在springboot新版本&#xff08;小编3.2.3&#xff09;在spring.data.xxx下了&#xff0c;如下所示&#xff0c;mongodb的配置在spring.data.mongodb下&#xff1a; 连接池相关参数配置-源码分析 拼接在…

vue3 删除对象中的属性,可以使用js里的delete,但需注意ts定义对象类型!

如上如&#xff0c;当使用delete 删除stateData中的属性时&#xff0c; 报错&#xff0c;意思为 TypeScript 错误“‘delete’ 运算符的操作数必须是可选的 什么原因呢&#xff1f;是因为我偷懒 缺少了ts定义类型 方法一&#xff1a; &#xff08;不推荐&#xff09; delete …

【网络安全 | 信息收集】JS文件信息收集工具LinkFinder安装使用教程

文章目录 前言安装教程使用教程 前言 JavaScript文件可能会泄露敏感信息&#xff0c;如注释中的机密信息、内部IP地址&#xff0c;以及包含未授权访问或其他漏洞的URL。手动检查这些信息效率低下&#xff0c;而该工具——LinkFinder&#xff0c;可用于自动收集JavaScript文件中…

Windows10系统中忘记MySQL数据库root权限登录密码

本文档所使用的MySQL版本为MySQL5.7>> mysqld_safe --skip-grant-tables&mysql -u root mysql在命令行中使用上面的命令登录MySQL&#xff0c;其中--skip-grant-tables允许用户跳过权限表进行无密码登录 >> UPDATE user SET authentication_stringPASSWORD(&q…

2024 年 Web 前端开发趋势

希腊哲学家赫拉克利特认为&#xff0c;变化是生命中唯一不变的东西。这句话适用于我们的个人生活、行业和职业领域。 尤其是前端开发领域&#xff0c;新技术、开发趋势、库和框架不断涌现&#xff0c;变化并不陌生。最近发生的一些事件正在改变开发人员构建网站和 Web 应用的方…

buuctf之ciscn_2019_c_1

ciscn_2019_c_1 一、查看属性二、静态分析三、动态分析四、思路五、exp 一、查看属性 首先还是必要的查看属性环节&#xff1a; 可以知道该文件是一个x86架构下的64位小端ELF文件&#xff0c;开启了栈不可执行&#xff08;NX&#xff09; 执行一下&#xff0c;先有一个选择&…

容联云QCon全球软件大会分享:大模型引领“营销服”创新实践

近日&#xff0c;QCon 全球软件开发大会正式召开。容联云大模型产品负责人唐兴才受邀出席&#xff0c;并分享营销服场景中&#xff0c;大模型的创新应用与实践。 唐兴才指出&#xff0c;在大模型浪潮的推动下&#xff0c;营销服场景正经历着前所未有的变革。面对激烈的市场竞争…

LineVul: 基于Transformer的行号级漏洞预测

文中提出一种基于Transformer的行号级漏洞预测方法 LineVul&#xff0c;以解决最先进的 IVDetect 方法的若干局限性。该方法通过对包含 188k C/C 函数的大规模真实数据集进行实证评估&#xff0c;LineVul 实现了&#xff1a;&#xff08;1&#xff09;函数级预测的 F1-measure …

sublime text的json快捷键

系统 macos 配置 sublime Text->Settings->Key Bindings 效果 可以看到&#xff0c;按&#xff1a;shiftcommandp&#xff0c;会出现快捷键窗口&#xff0c;打pretty&#xff0c;会出现Format JSON&#xff0c;最右侧显示⌘J&#xff0c;说明只需要macos的⌘和J同时按…

ASP.NET医院手麻信息系统源码 .NET6.0+VUE

目录 麻醉记录单 复苏记录单 麻醉文书 手术麻醉信息 1、 体征监控记录 2、 麻醉用药信息 3、 手术事件登记 4、 手术状态变更 5、 麻醉医师交接 6、 其他辅助操作 手麻信息系统是以服务围术期临床业务工作的开展为核心&#xff0c;通过与床边监护设备以及医院H…

物流单打印模板怎么设置,物流发货单打印软件操作教程

物流单打印模板怎么设置&#xff0c;物流发货单打印软件操作教程 一、前言 以下软件操作教程以&#xff0c;佳易王物流货运单管理系统软件为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 佳易王物流单管理系统软件直接在空白单上打印可以在卷纸…

AI论文速读 | 2024[VLDB]TFB:全面与公正的时间序列预测方法基准测试研究

论文标题&#xff1a;TFB: Towards Comprehensive and Fair Benchmarking of Time Series Forecasting Methods 作者&#xff1a;Xiangfei Qiu ; Jilin Hu&#xff08;胡吉林&#xff09; ; Lekui Zhou ; Xingjian Wu ; Junyang Du ; Buang Zhang ; Chenjuan Guo&#xff08;郭…

mybatisPlus数据字段填充

这里用到的时实体类User import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableName; import lombok.…

如何在ubuntu上使用clash

下载CLASH软件 修改配置文件 解压之后&#xff0c;将.env文件中的URL改为自己订阅的URL&#xff0c;然后再执行start.sh脚本 最后按照提示&#xff0c;将clash.sh添加到环境变量 如何修改端口 在start.sh中更改 祝大家在ubuntu上玩得开心

多高的学历才能轻松找到工作?这个热点有点扯吧~

先来唠唠 昨天刷脉脉的时候&#xff0c;热榜第一的内容吸引了我&#xff1a;多高的学历才能轻松找到工作&#xff1f; 现在这行情&#xff0c;不管多高得学历都很难说能轻松找到工作吧~ 评论区也有不少小伙伴发表自己的见解&#xff0c;比如&#xff1a; 学历固然是非常重要…

C++ 小项目 - 通讯录管理系统

C 小项目系列教程&#xff1a; 通讯录管理系统 ➡️➡️➡️本教程参考自 黑马程序员 C 视频课程 其中的 Markdown 文档&#xff0c;仅用于自己学习&#xff0c;源码发布在 Contact-Management。 文章目录 1. 系统需求2. 创建项目3. 菜单4. 主要功能4.1 添加联系人4.2 显示联系…

关于主干布线,你应该知道什么

所有大型建筑都需要复杂的通信网络才能有效运行。这需要多个不同的通信室和电缆将这些房间连接在一起。在这里&#xff0c;骨干布线是任何建筑物通信系统的重要组成部分&#xff0c;可以发挥作用。 那么&#xff0c;什么是骨干布线&#xff1f;它是做什么用的&#xff1f;它究…

Monaco Editor系列(四)版本对比、自定义右键菜单、光标滚动

前言&#xff1a;亲爱的小伙伴们&#xff0c;又见面了&#xff01;上一篇文章我们一起学习了 Monaco Editor 的几个功能&#xff0c;设置内容、多文件编辑、自定义主题&#xff1b;下面让我们继续Monaco Editor的旅程吧&#xff01; 前情提要&#xff1a; 上一篇文章我介绍了M…