Socket网络编程

news/2024/10/13 16:21:21

Socket编程

为了实现两台不同的机器能够进行通信,所有要使用到网络编程

IP地址与端口号

  • IP地址:用于标识网络上主机的位置,每台网络上的设备都有唯一的ip地址。
  • 端口号:用于标识主机上的哪个应用程序,一台主机上运行的很多应用程序,该数据是传送给哪个应用程序使用的通过端口号标识。

TCP与UDP

是数据传输层的两种通信协议,区别如下:

TCP

  • 面向有连接,即发送数据之前需要建立连接,

  • 传输可靠,适用于文件传输等对数据完整性高的场景

UDP

  • 面向无连接,传输不可靠,

  • 适用于视频流等对数据传输完整性不高的场景

字节序

字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序。由于不同的主机可能存储数据的字节序不同,不同字节序的主机进行数据交互时可能会造成数据错误

字节序有:

  • 小端字节序:数据的低位存储在低地址
  • 大端字节序:数据的高位存储在低地址
  • 网络字节序:大端字节序,网络传输时都是按大端进行传输

字节序转换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);		
  • h代表host,n代表net,,s代表short(两个字节),l代表long(4个字节)
  • 通过上面4个函数可以实现主机字节序和网络字节序之间的转换

Socket实现流程

网络编程函数

头文件:

#include <sys/socket.h>

socket()

函数原型:int socket(int domain, int type, int protocol);

函数作用:创建网络通信套接字;

返回值:成功时返回套接字(文件描述符),失败返回-1

参数说明:

  • domain:协议族,指定通信时用的协议族;常用选项如下:
    AF_UNIX, AF_LOCAL :Local communication,用于本地进程/线程间通信;
    AF_INET :IPv4 Internet protocols,用于IPV4网络通信;
    AF_INET6 :IPv6 Internet protocols,用于IPV6网络通信;

  • type:套接字类型,常用选项如下:
    SOCK_STREAM :流式套接字,唯一对应于TCP;
    SOCK_DGRAM :数据报套接字,唯一对应于UDP;
    SOCK_RAW :原始(透传)套接字;

  • protocol:
    通常填0,在type类型为SOCK_RAW时,需要该参数。

bind()

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

函数作用:绑定服务器相关信息,IP地址和端口号;

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

参数说明:

  • sockfd:通过socket()得到的文件描述符;

  • addr :指向struct sockaddr类型结构体变量的指针,包含了IP地址和端口号;实际使用时,如果是网络编程,一般都是定义struct sockaddr_in类型的变量,然后取该变量的地址强转为struct sockaddr*类型;

    //internet协议地址结构:struct sockaddr_in {       u_short sin_family;      // 协议族, AF_INET,2 bytes    u_short sin_port;        // 端口号,2 bytes  struct in_addr sin_addr; // IP地址结构体,4 bytes      char sin_zero[8];        // 8 bytes unused,作为填充}; 
    
    struct in_addr 
    {__be32 s_addr;    // 32位地址
    };
    
    //通用结构体
    struct sockaddr
    {    u_short  sa_family;    // 协议簇族, AF_xx char  sa_data[14];     // ip地址+端口};
    
  • addrlen:struct sockaddr类型结构体变量所占内存空间大小;

listen()

函数原型:int listen(int sockfd, int backlog);

函数作用:将主动套接字变为被动套接字。

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

参数说明:

  • sockfd:通过socket()得到的文件描述符。

  • backlog:指导在请求队列中允许的最大请求数。

accept()

函数原型:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

函数作用:阻塞等待客户端的连接请求,当由客户端请求连接时,该函数返回已经建立连接的新套接字(文件描述符),用于客户端和服务器通信;

返回值:成功时返回新的文件描述符,后面与客户端通信用的就是该返回的文件描述符,失败返回-1。

参数说明:

  • sockfd:通过socket()得到的文件描述符;
  • addr :指向struct sockaddr类型结构体变量的指针;用于存放连接过来的客户端的IP地址和端口号,实际使用时,如果不需要客户端的信息,可以直接填NULL;
  • addrlen:指向socklen_t类型变量的指针;表示struct sockaddr类型结构体变量所占内存空间大小;

connect()

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

函数作用:客户端调用该函数向服务器发起连接请求;

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

参数说明:

  • sockfd:通过socket()得到的文件描述符.
  • addr :指向struct sockaddr类型结构体变量的指针,用于填充服务端的IP与端口信息;
  • addrlen:struct sockaddr类型结构体变量所占内存空间大小;

数据收发

ssize_t write(int fd, const void *buf, size_t nbytes);
ssize_t read(int fd, void *buf, size_t nbytes);/*说明*函数均返回读写的字节个数,出错则返回-1*/

客户端与服务器通信

  • socket_service

    #include <stdio.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    int main()
    {int s_fd;int ret;char readBuf[128];char writeBuf[128] = {0};struct sockaddr_in s_addr;struct sockaddr_in c_addr;memset(&s_addr,0,sizeof(struct sockaddr_in));memset(&c_addr,0,sizeof(struct sockaddr_in));//1.创建套接字s_fd = socket(AF_INET,SOCK_STREAM,0);if(-1 == s_fd){perror("socket error");exit(-1);}//2.绑定ip地址和端口号s_addr.sin_family = AF_INET;s_addr.sin_port = htons(8989);inet_aton("192.168.137.115",&s_addr.sin_addr);bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));//3.监听listen(s_fd,10);while(1){//4.接受连接int clen = sizeof(struct sockaddr_in);int c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen);if(-1 == c_fd){perror("accept error\r\n");exit(-1);}printf("get connect:%s\r\n",inet_ntoa(c_addr.sin_addr));if(fork()==0){if(fork()==0){while(1){memset(writeBuf,0,sizeof(writeBuf));printf("input:");gets(writeBuf);write(c_fd,writeBuf,sizeof(writeBuf));}}while(1){//5.readmemset(readBuf,0,sizeof(readBuf));ret = read(c_fd, readBuf, 128);if(-1 == ret){perror("read error\r\n");exit(-1);}else{printf("get message:%s\r\n",readBuf);}}break;}}return 0;
    }
    
  • socket_cilent

    #include <stdio.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>int main()
    {int c_fd;int ret;struct sockaddr_in c_addr;char readBuf[128];char writeBuf[128] = {0};//1.创建套接字c_fd = socket(AF_INET,SOCK_STREAM,0);if(-1 == c_fd){perror("socket error");exit(-1);}//设置服务器IP及端口号c_addr.sin_family=AF_INET;c_addr.sin_port=htons(8989);inet_aton("192.168.137.115",&c_addr.sin_addr);//2.connectif(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1){perror("connetc error");exit(-1);}while(1){if(fork()==0){while(1){//3.writememset(writeBuf,0,sizeof(writeBuf));printf("input:");gets(writeBuf);write(c_fd,writeBuf,strlen(writeBuf));}}while(1){//4.readmemset(readBuf,0,sizeof(readBuf));ret = read(c_fd,readBuf,128);if(-1 == ret){perror("read error");exit(-1);}else{printf("get message:%s\r\n",readBuf);}  }}return 0;
    }
    

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

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

相关文章

golang初学:交叉编译

go version go1.22.1 windows/amd64 Windows 11 + amd64 x86_64 x86_64 GNU/Linux ---序章 golang 支持 跨平台,支持的方式 是 在一个平台 编译其它平台的可执行程序。 本文 介绍 Windows 11(开发主机) 上 编译 Linux(目标主机) 上的可执行程序。#go build开发主机 和 目标…

DRF之三大认证

一、认证 1、自定义认证 在前面说的 APIView 中封装了三大认证,分别为认证、权限、频率。认证即登录认证,权限表示该用户是否有权限访问接口,频率表示用户指定时间内能访问接口的次数。整个请求最开始的也是认证。 (1)需求登陆认证 用户登陆成功--》签发token 以后需要登陆…

Vue入门到关门之Vue项目工程化

一、创建Vue项目 1、安装node环境官网下载,无脑下一步,注意别放c盘就行Node.js — Run JavaScript Everywhere (nodejs.org)需要两个命令npm---->pip node--->python装完检查一下,hello world检测,退出crtl+c2、搭建vue项目环境装cnpm 这个包,下载东西会快很多,装模…

第6讲需求分析--uml用例图

用例图 一.识别参与者 参与者在系统外所以画图时画在框外。系统用例图比业务用例图更完善所以经常让画的是系统用例图。在商品销售系统里:参与者是顾客。 在会计系统里:参与者是商品销售系统。 二.关系 1.参与者之间 泛化关系子指向父 2.参与者和用例之间 关联关系3.用例和用…

认知提升的方法

认知提升的方法一、什么是认知 经验是对于过往经历的总结归纳,当把这种经验传授给别人时,这种经验对别人来说就是知识。所以,知识是人脑对客观事物的信息沉淀。 技能是人们通过练习而获得的动作方式和系统,例如操作技能中的PS技术、木工技术、电工技术、水工技术等,而能力…

c#胖东来小程序自动购物程序(接单,windows桌面程序、linux程序、网络应用等等)

一、程序效果 自动打开胖东来小程序,自动购物 二、实现 先截屏,然后利用opencv库识别下一步按键所在位置,然后使用mouse_event控制鼠标,模拟人的动作 第一步,截取屏幕static Bitmap CaptureScreen() {int screenWidth = Screen.PrimaryScreen.Bounds.Width;int screenHeig…

优先级翻转实验以及分析现象

优先级翻转实验以及分析现象 优先级翻转指的是高优先级的任务反而慢执行,低优先级的任务反而优先执行。优先级翻转在抢占式内核中是非常常见的,但是在实时操作系统中是不允许出现优先级翻转的,因为优先级翻转会破坏任务的预期顺序,可能会导致未知的严重后果。上图中三个任务…

十日冲刺其六

今天完成了:用户可以自主删除自己发表的空间动态 遇到的困难:不能在浏览空间时进行删除动态,限制因素较多 明天打算,优化一下动态删除功能