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.mzph.cn/news/827324.shtml

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

相关文章

每日一题---移除链表元素

文章目录 前言1.题目2.分析思路3.参考代码 前言 Leetcode–-移除链表元素 1.题目 2.分析思路 首先要创建一个新的链表&#xff0c;在定义三个指针&#xff0c;newHead&#xff0c;newTail和pcur&#xff0c;分别代表新链表头&#xff0c;新链表尾以及用于遍历原链表。 其次是…

Rust入门-所有权

一、为什么、是什么、怎么用 1、为什么Rust要提出一个所有权和借用的概念 所有的程序都必须和计算机内存打交道&#xff0c;如何从内存中申请空间来存放程序的运行内容&#xff0c;如何在不需要的时候释放这些空间&#xff0c;成为所有编程语言设计的难点之一。 主要分为三种…

git merge 和 git rebese的区别

git merge 和 git rebese的区别 拉取分支和合并代码会涉及两种选择&#xff0c;git merge 和 git rebase&#xff1a; rebase&#xff1a;变基&#xff0c;会有一个干净的分支&#xff0c;但是对于记录来源不够清楚merge&#xff1a;合并&#xff0c;git 分支看起来比较混乱&…

CentOS 7虚拟机配置静态IP地址(一)

IP地址的配置 以下几个地址需要记住&#xff0c;在配置中使用 &#xff08;1&#xff09;查看MAC地址&#xff08;点击菜单虚拟机-设置-网络适配器-高级-记住MAC地址&#xff09; &#xff08;2&#xff09;查看子网掩码和网关IP&#xff08;点击菜单编辑-虚拟网络编辑器-选择…

机器学习-10-神经网络python实现-从零开始

文章目录 总结参考本门课程的目标机器学习定义从零构建神经网络手写数据集MNIST介绍代码读取数据集MNIST神经网络实现测试手写的图片 带有反向查询的神经网络实现 总结 本系列是机器学习课程的系列课程&#xff0c;主要介绍基于python实现神经网络。 参考 BP神经网络及pytho…

Reactor 模式

目录 1. 实现代码 2. Reactor 模式 3. 分析服务器的实现具体细节 3.1. Connection 结构 3.2. 服务器的成员属性 3.2. 服务器的构造 3.3. 事件轮询 3.4. 事件派发 3.5. 连接事件 3.6. 读事件 3.7. 写事件 3.8. 异常事件 4. 服务器上层的处理 5. Reactor 总结 1…

公钥密码学Public-Key Cryptography

公钥或非对称密码学的发展是整个密码学历史上最伟大的&#xff0c;也许是唯一真正的革命。The development of public-key, or asymmetric, cryptography is the greatest and perhaps the only true revolution in the entire history of cryptography. 公钥算法基于数学函数…

node.js如何实现留言板功能?

一、实现效果如下&#xff1a; 20240422_160404 二、前提配置&#xff1a; 配置&#xff1a;需要安装并且导入underscore模板引擎 安装&#xff1a;在控制台输入npm install underscore -save 文件目录配置&#xff1a; 1》在文件里建一个data文件夹&#xff0c;此文件夹下…

ContextMenuStrip内容菜单源对象赋值学习笔记(含源码)

一、前言 MetroTileItem属于第三方控件,无法定义ContextMenuStrip属性 想实现某子项点击菜单时,与源控件(按钮metroTileItem)的某值对应,用于动态控制按钮的状态或方法 1.1 效果 二、实现方法 2.1 方法1 (代码,说明见注释) private void metroTileItem_MouseDown(o…

【题解】AB5 点击消除(栈)

https://www.nowcoder.com/practice/8d3643ec29654cf8908b5cf3a0479fd5?tpId308&tqId40462&ru/exam/oj 把string当栈用&#xff0c;扫一遍就可以了&#xff0c;时间复杂度O(n) #include <iostream> #include <string> using namespace std;int main() {…

向量的点积和叉积的几何意义

1. 点积 点积(dot product)&#xff0c;又称标量积&#xff08;scalar product&#xff09;。结果等于。 可用于 判断的是否垂直求投影长度求向量是抑制作用还是促进作用 2. 叉积 叉积(cross product)&#xff0c;又称为向量积(vector product)。模长等于&#xff0c;方向…

Golang | Leetcode Golang题解之第43题字符串相乘

题目&#xff1a; 题解&#xff1a; func multiply(num1 string, num2 string) string {if num1 "0" || num2 "0" {return "0"}m, n : len(num1), len(num2)ansArr : make([]int, m n)for i : m - 1; i > 0; i-- {x : int(num1[i]) - 0fo…

详细说说,中介怎么做!CLHLS数据库探索抑郁症状的中介作用发文二区

零基础CHARLS发论文&#xff0c;不容错过&#xff01; 长期回放更新指导&#xff01;适合零基础&#xff0c;毕业论文&#xff0c;赠送2011-2020年CHARLS清洗后的数据全套代码&#xff01; 2024年3月28日&#xff0c;中国学者用CLHLS数据库最新数据&#xff08;2018年&#xff…

java-Arrays

一、Arrays的概述 Arrays是操作数组的工具类 二、Arrays的常用方法 Arrays的常用方法基本上都被static静态修饰&#xff0c;因此在使用这些方法时&#xff0c;可以直接通过类名调用 1.toString 语法&#xff1a;Arrays.toString(数组) 用于将数组的元素转换为一个字符串&a…

蓝桥杯第17169题——兽之泪II

问题描述 在蓝桥王国&#xff0c;流传着一个古老的传说&#xff1a;在怪兽谷&#xff0c;有一笔由神圣骑士留下的宝藏。 小蓝是一位年轻而勇敢的冒险家&#xff0c;他决定去寻找宝藏。根据远古卷轴的提示&#xff0c;如果要找到宝藏&#xff0c;那么需要集齐 n 滴兽之泪&#…

Git | 分支管理

Git | 分支管理 文章目录 Git | 分支管理1、理解分支2、创建分支&&切换分支3、合并分支4、删除分支5、合并冲突6、分支管理策略合并分支模式实际工作中分支策略bug分支删除临时分支 1、理解分支 分支就类似分身。 在版本回退中&#xff0c;每次提交Git都会将修改以git…

简单学量化——pandas的应用26——sort_values函数5

简单学量化——pandas的应用26——sort_values函数5 sort_values是pandas中的排序函数&#xff0c;语法如下&#xff1a; DataFrame.sort_values(by,axis0,ascendingTrue,inplaceFalse,kindquicksort,na_positionlast, ignore_indexFalse,keyNone) 前面我们学习了by、axis、a…

C++之写时复制(CopyOnWrite)

设计模式专栏&#xff1a;http://t.csdnimg.cn/4j9Cq 目录 1.简介 2.实现原理 3.QString的实现分析 3.1.内部结构 3.2.写入时复制 4.示例分析 5.使用场景 6.总结 1.简介 CopyOnWrite (COW) 是一种编程思想&#xff0c;用于优化内存使用和提高性能。COW 的基本思想是&am…

go的编译以及运行时环境

开篇 很多语言都有自己的运行时环境&#xff0c;go自然也不例外&#xff0c;那么今天我们就来讲讲go语言的运行时环境&#xff01; 不同语言的运行时环境对比 我们都知道Java的运行时环境是jvm &#xff0c;javascript的运行时环境是浏览器内核 Java -->jvm javascript…

FastWiki一分钟本地离线部署本地企业级人工智能客服

介绍 FastWiki是一个开源的企业级人工智能客服系统&#xff0c;它使用了一系列先进的技术和框架来支持其功能。 技术栈 前端框架&#xff1a;React LobeUI TypeScript后端框架&#xff1a;MasaFramework 基于 .NET 8动态函数&#xff1a;基于JavaScript V8引擎实现向量搜索…