Linux学习之网络编程2(socket,简单C/S模型)

这篇具有很好参考价值的文章主要介绍了Linux学习之网络编程2(socket,简单C/S模型)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

写在前面

Linux网络编程我是看视频学的,Linux网络编程,看完这个视频大概网络编程的基础差不多就掌握了。这个系列是我看这个Linux网络编程视频写的笔记总结。


网络字节序

  • 小端法:pc本地存储,高位存高地址,低位存低地址。
  • 大端法:网络存储,高位存低地址,低位存高地址。

由此我们看到本地和网络的存储方式不一样,所以每次建立连接都要转换,下面我来介绍一些关于大端法和小端法的转换函数。

  • htonl:本地——>网络,转换的是IP
  • htons:本地——>网络,转换的是端口
  • ntohl:网络——>本地,转换的是IP
  • ntohs:网络——>本地,转换的是端口

其实这四个函数非常好记,h代表host表示本地n代表network表示网络l代表long存的IPs代表short存的是端口。(所以说学好英语还是很重要的

IP转换函数

int inet_pton(int af, const char *src, void *dst);
功能:本地字节序(string IP)——> 网络字节序。
参数:

  • af:AF_INET 或者AF_INET6
  • src:传入参数,IP地址(点分十进制)
  • dst:传出参数,转换后的网络字节序。
    返回值:
  • 成功,1
  • 异常:0,说明src指向的不是一个有效的IP地址。
  • 失败,-1

const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
功能:网络字节序——>本地字节序(string IP)
参数:

  • af:AF_INET 或者AF_INET6
  • src: 网络字节序IP地址
  • dst:本地字节序(string IP)
  • sizedst的大小。
    返回值:
  • 成功,dst
  • 失败,NULL

Socket套接字

套接字概念

在通信过程中,套接字一定是 成对出现。
一个文件描述符指向一个套接字(该套接字内部由借助内核缓冲区实现读写)
Linux学习之网络编程2(socket,简单C/S模型),# Linux网络编程,Linux,linux,学习,网络,Linux网络编程,套接字socket

网络通信的流程

Linux学习之网络编程2(socket,简单C/S模型),# Linux网络编程,Linux,linux,学习,网络,Linux网络编程,套接字socket

  • 服务器端:
    1. 先用socket()生成一个套接字lfd用来监听
    2. bind()对第一步生成的套接字绑定地址结构(绑的是服务器的地址结构)
    3. listen()函数设置lfd的监听上限,最大是128.
    4. accept()阻塞直到有客户端请求连接。
    5. 处理请求,得到客户端的地址结构,和用于通信的套接字cfd(这个套接字是调用accept()后返回值)
    6. 成功建立连接,进行通信,处理业务逻辑。
  • 客户端:
    1. 先用socket() 生成一个套接字sfd
    2. 使用connect()请求与服务器建立连接
    3. 成功建立连接,进行通信,处理业务逻辑。

相关函数介绍

socket函数

语法:

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

功能:

创建一个套接字

参数:
  • domain:AF_INETAF_INET6
  • type:数据传输协议,SOCK_STREAM(表示用流式协议,使用TCP通信传这个参数)或SOCK_DGRAM(表示用报式协议,使用UDP通信传这个参数)。(后面用本地套接字通信还会学到SOCK_LOCAL,这个后面学到再介绍)
  • protocol:默认传0,表示让系统自动根据type来选择,SOCK_STREAM的代表协议是TCPSOCK_DGRAM的是UDP
返回值:
  • 成功,新套接字所对应的文件描述符
  • 失败:-1 ,error

bind函数

语法:

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

功能:

socket绑地址结构

参数
  • sockfd:socket函数的返回值,要绑定的套接字
  • addr:传入参数,要绑定的地址结构。
  • addrlensizeof(addr) 地址结构的大小

addr类型是一个结构体,上面写的是struct sockaddr结构,实际我们创建的时候要创建struct sockaddr_in,它里面有三个成员变量。

  • sin_family:和当时创建套件字的第一个参数一样,传AF_INET
  • sin_port:绑定的端口号,只不过要转换成网络字节序
  • sin_addr.s_addr:这个是最复杂的,sin_addr本身又是一个结构体,但里面只有一个成员s_addr,所以就直接拿出来了。传的是绑定的IP地址,同样也要转换。

下面给个example,最后传的时候要类型强转一下
Linux学习之网络编程2(socket,简单C/S模型),# Linux网络编程,Linux,linux,学习,网络,Linux网络编程,套接字socket

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

listen函数

语法:

int listen(int sockfd, int backlog);

功能:

设置同时与服务器建立连接的客户端数量的上限

参数:
  • sockfd:要监听的套接字
  • backlog:上限值,最大是128
返回值:
  • 成功,0
  • 失败,-1

accept函数

语法:

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

功能:

阻塞等待客户端建立连接

参数
  • sockfd:监听的套接字
  • addr:传出参数,表示建立连接的客户端的地址结构(IP+端口)
  • addrlen:传入传出参数。入:addr的大小,出:客户端addr的实际大小
返回值
  • 成功,能与服务器进行数据通信的套接字的文件描述符,即服务器用这个便可与客户端
  • 失败,-1

connect函数

语法:

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

功能:

使用客户端现有的套接字与服务器建立连接

参数:
  • sockfd:客户端自己的套接字
  • addr:服务器的地址结构
  • addrlen:服务器地址结构的长度
返回值:
  • 成功,0
  • 失败,-1

demo

说明

我们来写一个小demo,实现的功能是:客户端与服务器建立连接后,服务器可以将客户端发送的小写字母变成大写然后发送回去

服务器源代码

#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<ctype.h>

#define PORT 6666

void sys_err(char * str)
{
	perror(str);
	exit(1);
}

int main()
{
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(sfd==-1)
		sys_err("socker error");
	struct sockaddr_in addr_ser,addr_cli;
	addr_ser.sin_family=AF_INET;
	addr_ser.sin_port=htons(PORT);
	addr_ser.sin_addr.s_addr=htonl(INADDR_ANY);
	int res=bind(sfd,(struct sockaddr *)&addr_ser,sizeof addr_ser);
	if(res==-1)
		sys_err("bind error");
	res=listen(sfd,128);
	if(res==-1)
		sys_err("listen error");
	socklen_t addr_cli_len=sizeof addr_cli;
	int cfd=accept(sfd,(struct sockaddr*)&addr_cli,&addr_cli_len);
	if(res==-1)
		sys_err("accept error");
	char client_IP[1024];
	printf("client IP is %s,port is %d\n",inet_ntop(AF_INET,&addr_cli.sin_addr.s_addr,&client_IP,sizeof client_IP),ntohs(addr_cli.sin_port));
	while(1)
	{
		char buf[BUFSIZ];
		int n=read(cfd,buf,sizeof buf);
		write(STDOUT_FILENO,buf,n);
		for(int i=0;i<n;i++)
			buf[i]=toupper(buf[i]);
		write(cfd,buf,n);
	}
	return 0;
}

客户端源代码

#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<arpa/inet.h>

#define PORT 6666

void sys_err(char* str)
{
	perror(str);
	exit(1);
}

int main()
{
	int cfd=socket(AF_INET,SOCK_STREAM,0);
	if(cfd==-1)
		sys_err("socket error");
	struct sockaddr_in addr_ser;
	addr_ser.sin_family=AF_INET;
	addr_ser.sin_port=htons(PORT);
	inet_pton(AF_INET,"127.0.0.1",&addr_ser.sin_addr.s_addr);
	int res=connect(cfd,(struct sockaddr*)&addr_ser,sizeof addr_ser);
	if(res==-1)
		sys_err("connect error");
	while(1)
	{
		char buf[BUFSIZ];
		int n=read(STDIN_FILENO,buf,sizeof buf);
		write(cfd,buf,n);
		read(cfd,buf,n);
		write(STDOUT_FILENO,buf,n);
	}
	return 0;
}

效果展示

Linux学习之网络编程2(socket,简单C/S模型),# Linux网络编程,Linux,linux,学习,网络,Linux网络编程,套接字socket

写好服务器后,可以再打开一个终端先用命令nc IP portl来测试服务器,命令里的IP是服务器的实际IP,port是服务器实际的端口


写在最后

个人亲身经验:我们学习的一系列Linux命令,一定要自己亲手去敲。不要只是看别人敲代码,不要只是停留在眼睛看,脑袋以为自己懂了,等你实际上手去敲会发现许许多多的这样那样的问题。毕竟“实践出真知”。


如果你觉得我写的题解还不错的,请各位王子公主移步到我的其他题解看看

  1. 数据结构与算法部分(还在更新中):
  • C++ STL总结 - 基于算法竞赛(强力推荐
  • 动态规划——01背包问题
  • 动态规划——完全背包问题
  • 动态规划——多重背包问题
  • 动态规划——分组背包问题
  • 动态规划——最长上升子序列(LIS)
  • 二叉树的中序遍历(三种方法)
  • 最长回文子串
  • 最短路算法——Dijkstra(C++实现)
  • 最短路算法———Bellman_Ford算法(C++实现)
  • 最短路算法———SPFA算法(C++实现)
  • 最小生成树算法———prim算法(C++实现)
  • 最小生成树算法———Kruskal算法(C++实现)
  • 染色法判断二分图(C++实现)
  1. Linux部分(还在更新中):
  • Linux学习之初识Linux
  • Linux学习之命令行基础操作
  • Linux学习之基础命令(适合小白)
  • Linux学习之权限管理和用户管理
  • Linux学习之制作静态库和动态库
  • Linux学习之makefile
  • Linux学习之系统编程1(关于读写系统函数)
  • Linux学习之系统编程2(关于进程及其相关的函数)
  • Linux学习之系统编程3(进程及wait函数)
  • Linux学习之系统编程4(进程间通信)
  • Linux学习之系统编程5(信号)
  • Linux学习之系统编程6(线程)
  • Linux学习之系统编程7(线程同步/互斥锁/信号量/条件变量)
  • Linux学习之网络编程(纯理论)

✨🎉总结

“种一颗树最好的是十年前,其次就是现在”
所以,
“让我们一起努力吧,去奔赴更高更远的山海”
Linux学习之网络编程2(socket,简单C/S模型),# Linux网络编程,Linux,linux,学习,网络,Linux网络编程,套接字socket
如果有错误❌,欢迎指正哟😋

🎉如果觉得收获满满,可以动动小手,点点赞👍,支持一下哟🎉文章来源地址https://www.toymoban.com/news/detail-790177.html

到了这里,关于Linux学习之网络编程2(socket,简单C/S模型)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 「网络编程」第二讲:网络编程socket套接字(三)_ 简单TCP网络通信程序的实现

    「前言」文章是关于网络编程的socket套接字方面的,上一篇是网络编程socket套接字(二),下面开始讲解!  「归属专栏」网络编程 「主页链接」个人主页 「笔者」枫叶先生(fy) 「枫叶先生有点文青病」「每篇一句」 I do not know where to go,but I have been on the road. 我不知

    2024年02月11日
    浏览(37)
  • Linux学习之网络编程1(纯理论)

    刚刚更新完Linux系统编程,特别推荐大家去看的Linux系统编程,总共44个小时,老师讲的非常好,我是十天肝完的,每天大概看20集,每天还要以写blog的形式来写笔记来总结一下,虽然这十天有点累,但是这套视频值得这些时间的付出。我现在在学习Linux网络编程,学习看的视

    2024年01月24日
    浏览(17)
  • Linux学习之网络编程3(高并发服务器)

    Linux网络编程我是看视频学的,Linux网络编程,看完这个视频大概网络编程的基础差不多就掌握了。这个系列是我看这个Linux网络编程视频写的笔记总结。 问题: 根据上一个笔记,我们可以写出一个简单的服务端和客户端通信,但是我们发现一个问题——服务器只能连接一个

    2024年02月01日
    浏览(36)
  • Linux网络编程- 原始套接字(Raw Socket)

    原始套接字(Raw Socket)提供了一种机制,允许应用程序直接访问底层传输协议,绕过操作系统提供的传输层接口。这种套接字通常用于实现新的协议或对现有协议进行低级别的操作。 以下是对原始套接字的详细介绍: 定义与用途 : 原始套接字是直接基于网络层(如IP)的。

    2024年02月07日
    浏览(33)
  • Linux socket网络编程实战(tcp)实现双方聊天

    在上节已经系统介绍了大致的流程和相关的API,这节就开始写代码! 回顾上节的流程: 创建一个NET文件夹 来存放网络编程相关的代码: 这部分先实现服务器的连接部分的代码并进行验证 server1.c: 代码验证: 先编译并运行这部分代码: 可见,此时没有客户端进行连接,程

    2024年02月03日
    浏览(42)
  • Linux网络编程:socket实现client/server通信

    阅读 UNIX网络编程 卷1:套接字联网API 第3版 的前4个章节,觉得有必要对书籍上的源码案例进行复现,并推敲TCP的C/S通信过程。 📌 测试环境:CentOS7.6 x64 编译server.c 和 client.c gcc server.c -g -std=gnu99 -o server 和 gcc client.c -g -std=gnu99 -o client 运行测试: 📌 server.c仅仅实现对单个客户

    2024年02月03日
    浏览(30)
  • Python网络编程(一)——了解IP和端口的基础知识以及socket的简单实现

    Python网络编程(一)——了解IP和端口的基础知识以及socket的简单实现 IP(Internet Protocol) 地址是唯一标识互联网上连接至计算机或其他设备的地址。每一个设备在 IP 网络中拥有一个不同的 IP 地址,它由 32 位二进制数组成,通常表示为四个从 0 到 255 的十进制数之间用 (.)

    2024年02月04日
    浏览(47)
  • Linux网络编程:socket、客户端服务器端使用socket通信(TCP)

    socket(套接字),用于网络中不同主机间进程的通信。 socket是一个伪文件,包含读缓冲区、写缓冲区。 socket必须成对出现。 socket可以建立主机进程间的通信,但需要协议(IPV4、IPV6等)、port端口、IP地址。          (1)创建流式socket套接字。                 a)此s

    2024年02月11日
    浏览(45)
  • 【探索Linux】—— 强大的命令行工具 P.26(网络编程套接字基本概念—— socket编程接口 | socket编程接口相关函数详细介绍 )

    本文将深入探讨使用套接字进行网络通信的基本步骤,包括创建套接字、绑定地址、监听连接(对于服务器端)、连接远程主机(对于客户端)、以及发送和接收数据等操作。套接字编程涉及一系列系统调用和函数,如 socket() 、 bind() 、 listen() 、 connect() 、 send() 、 recv() 等。

    2024年03月10日
    浏览(63)
  • Linux网络编程:socket & fork实现clients/server通信

    UNIX网络编程:socket实现client/server通信 随笔简单介绍了TCP Server服务单客户端的socket通信,但是并未涉及多客户端通信。 对于网络编程肯定涉及到多客户端通信和并发编程 (指在同时有大量的客户链接到同一服务器),故本随笔补充这部分知识。 而且并发并发编程涉及到多进程

    2024年02月05日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包