Socket 通信

news2024/11/22 16:27:12

文章目录

    • Socket 通信创建流程图
    • 通信示例
    • 对一些概念进行讲述
    • 对Socke 编程所用的函数进行讲解

网络通信 和 Socket

Socket 通信流程图 :

通信示例 

对Socket 编程有一个初步的了解, 看看具体代码是如何实现的. 

示例的主要功能:  实现大小写的转化,客户端发送数据

服务器端进行处理,再返回给客户端.

服务器端的实现   echo_socket.c

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

#define SERVER_PORT  666     //服务器的端口号

int main(void){
    
    int sock;//代表信箱
    struct sockaddr_in server_addr; //标签,保存端口号,ip地址等

    //1, 创建信箱
    sock = socket( AF_INET , SOCK_STREAM , 0);
    
    //2. 清空标签,写上地址和端口号
    bzero( &server_addr ,sizeof(server_addr));
    server_addr.sin_family = AF_INET; //选择协议族IPV4
    server_addr.sin_addr.s_addr = htonl( INADDR_ANY ); //监听本地所有ip地址
    server_addr.sin_port = htons( SERVER_PORT ); //绑定我们的端口号

    //3. 将我们的标签贴到信箱上
    bind(sock ,(struct sockaddr *)&server_addr,sizeof(server_addr));

    //4. 将我们的信箱挂到传达室,这样,保安就可以接收信件了
    listen(sock, 128);    //这里的128表示同时可以接收的信件数量

    //万事俱备,只等来信
    printf("等待客户端的来信\n");
   
    int done =1;
    //不断接受来信
    while( done ){
    	struct sockaddr_in client;
	int client_sock,len;
	char client_ip[64];
	char buff[256];

	socklen_t client_addr_len;
	client_addr_len = sizeof(client);
	client_sock = accept(sock ,(struct sockaddr *)&client, &client_addr_len);
    //打印客户端ip地址和端口号
	//inet_ntop  将网络字节序转化成字符串
	printf("client ip: %s\t port : %d\n",
	      inet_ntop( AF_INET, &client.sin_addr.s_addr,client_ip,sizeof(client_ip)), ntohs(client.sin_port));
	
	//5 、读取客户端发送的数据   read()
	len=read(client_sock , buff , sizeof(buff)-1);
	//手动添加字符串结束符
	buff[len]='\0';
	//打印读取的信息
	printf("recive :%s recive len :%d \n",buff,len);
        /* 完成大小写转换 */
	int i=0;
	for(i ; i< len ;i++)
	{
      if(buff[i]>='a' && buff[i] <= 'z'){    //小写字母
	     	buff[i]-=32;
	  }else if(buff[i]>='A' && buff[i] <= 'Z'){
	     	buff[i]+=32;
	  }
	 // buff[i]=toupper(buff[i]);
	}
	
	//6. 将读取到的信息写回去
	len = write( client_sock, buff, len ) ;
	printf("write finaled  :%s  len: %d\n", buff, len );
	//7. 关闭客户端
	close( client_sock );	
    }
    return 0;
}

客户端的实现  echo.client.c 

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

#define SERVER_PORT 666
#define SERVER_IP "127.0.0.1"    //本地环回地址

int main(int argc , char *agrv[]){
   
   int sockfd;     //定义一个邮箱
   char *message; 
   struct sockaddr_in serveraddr;    //定义标签,包括端口号和ip
   //清空标签
   memset( &serveraddr ,0 ,sizeof(serveraddr));
   if( argc!=2 ){
       fputs("usage : echo_client message \n",stderr);
       exit(1);
   }
   message = agrv[1];
   printf("message : %s\n",message);
   
   //创建信箱
   sockfd = socket ( AF_INET ,SOCK_STREAM , 0 );
   //写上端口号和ip
   serveraddr.sin_family = AF_INET ;  //网络簇
   inet_pton( AF_INET ,SERVER_IP ,&serveraddr.sin_addr);
   serveraddr.sin_port= htons(SERVER_PORT);       //写上端口号
    
   //连接信箱
   connect( sockfd ,(struct sockaddr *)&serveraddr, sizeof(serveraddr)); 
   
   //写数据
   int len;
   char buff[64];
   write( sockfd ,message , sizeof(message)-1);
   
   len = read (sockfd , buff , sizeof(buff)-1);

    if(len >0 ){
        buff[len]='\0';
        printf("recive :%s\n",buff);
    }else{
        printf("error\n");
    }

    printf("finished. \n");

    close(sockfd);
    

    return 0;
}

结果显示:

概念讲述 :

  • 套接字
  • 网络字节序
  • sockaddr 数据结构
  • ip地址转换函数

套接字(socket):

表示进程在网络上的一个连接点。每个套接字都有一个唯一的端口号和IP地址,用于标识该套接字所连接的远程主机和端口, 欲建立连接的两个进程各自有应该socket 来标识, 那么这两个socket 就组成一个 socke pari 就唯一标识一个连接。

网络字节序:

计算机中有两种字节序

大端字节序   - > 低地址高字节, 高地址低字节

小端字节序   - > 低地址低字节, 高地址高字节

内存中的多字节数据相对于内存地址有大端和小端之分 , 磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分。

网络数据流同样有大端小端之分。

发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出,接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存,因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址。

TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节。

 如何实现网络网络字节序和主机字节序的转换。

//包含头文件

#include <arpa/inet.h>

uint32_t htonl ( uint32_t  hostlong ) ;

uint16_t htons ( uint16_t  hostlong) ;

uint32_t ntopl ( uint32_t  hostlong ) ;

uint16_t  ntohs ( uint16_t  hostlong ) ;

/*

1、h  - >  host  (主机)

2、n  - >  network ( 网络 )

3 、l   - >  32位长整型

4、 s  - >  16位短整形 

5、to  - > 转换的意思可以理解成

*/

sockaddr 数据结构:

内部结构:

struct sockeaddr{
    sa_family_t  sa_family ;    //网络地址族, 如ipv4 (AF_INET)
    char sa_data[14];           //14字节的地址数据
}

struct sockeaddr_in{
    sa_family_t   sin_family;
    in_port_t   sin_port;       //端口号
    struct  in_addr_sin_addr;   //网络地址 
}


struct  in_addr_sin_addr{
    uint32_t  s_addr;          //网络字节序地址
}

ip地址转换函数:

//头文件

#include <arpa/inet.h>

// //网络协议地址(如IPv4或IPv6地址)转换为二进制格式

int inet_pton ( int  af , const char  * , char  *src , void *dst ) ;     

//将一个二进制格式的网络协议地址(如IPv4或IPv6地址)转换为字符串形式

const char * inet_ntop ( int af ,const void  *src ,char *dst ,socklen_t   size );

Socket 编程函数

socket() 函数  :

打开一个网络通讯端口,如果成功的话,就像open()一样返回一个文件描述符,这里就是相当于创建一个套接字 , 如果失败则返回  -1 。

#include < sys/types.h >       // 需要的头文件

#include < sys/socket.h >

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

// 参数说明

domain  :   地址族

这个参数用于指定套接字所使用的地址族(Address Family),它决定了套接字通信所使用的协议和网络地址的类型。

常用的地址族有AF_INET(IPv4网络)、AF_INET6(IPv6网络)等。在大多数情况下,我们使用AF_INET来创建套接字。  

type  :    套接字类型

这个参数用于指定套接字的类型,即数据传输的方式。常用的套接字类型有SOCK_STREAM(流套接字)和SOCK_DGRAM(数据报套接字)。

SOCK_STREAM 表示可靠的、面向连接的通信,通常使用TCP协议;而SOCK_DGRAM表示不可靠的、无连接的通信,通常使用UDP协议。根据实际需求选择合适的套接字类型。

protocol   :     协议      ( 默认0 ,一般情况不需要我们填写 )

这个参数用于指定套接字所使用的具体协议。

一般情况下,我们可以将这个参数设置为0,表示使用默认协议。

对于SOCK_STREAM类型的套接字,默认协议是TCP;对于SOCK_DGRAM类型的套接字,默认协议是UDP。如果需要使用其他特定的协议,可以根据协议类型设置这个参数。

bind( )   函数

将套接字绑定到指定的地址和端口。

#include < sys/types.h >

#include < sys/socket.h >

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

//  参数说明

sockfd   :   套接字 ,  由socket()函数返回的套接字描述符。

addr  :    指向套接字地址结构的指针,它包含了要绑定的IP地址和端口号。

               对于IPv4,这个地址结构通常是struct sockaddr_in类型。

  

addrlen  :   地址结构的长度    sizeof()  求出 

bind()  方法会在指定的地址和端口上绑定套接字。

如果绑定成功,返回0;如果绑定失败,返回-1,并设置相应的错误码。

  • 在调用bind()方法之前,必须确保已经使用socket()函数成功创建了套接字。
  • 绑定的IP地址和端口号应该有效且可用,避免和其他进程冲突。
  • 如果绑定的地址和端口已经被占用,将会导致绑定失败。

listen( )  函数 : 

用于将套接字转换为被动套接字,使其能够接受其他主机的连接请求。

它通常用于服务器端,使服务器能够监听并接受客户端的连接。

#include < sys/types .h >

#include < sys/socket.h >

int  listen ( int  sockfd  , int  backlog )  ;

//  参数说明 

sockfd   :     套接字

backlog  :  这个参数指定了同时等待处理的连接请求的最大数量。

                  当多个客户端同时向服务器发起连接请求时,如果连接请求的数量超过了                                backlog 指定的值,多余的连接请求可能会被拒绝。   

如果listen()函数调用成功,返回0;如果调用失败,返回-1。

使用listen()函数后,服务器就进入了“监听”状态,等待客户端的连接请求。

accept (  )  函数  :

用于接受从客户端发起的连接请求。

一旦有连接请求到达,accept() 函数会创建一个新的套接字,用于与客户端进行通信,并返回这个新套接字的描述符。

#include < sys/types.h >

#include < sys/socket.h >

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

// 参数说明

sockefd   :   套接字

addr   :      指向套接字地址结构的指针,它包含了要绑定的IP地址和端口号。

                 对于IPv4,这个地址结构通常是struct sockaddr_in类型。

                 如果不关心客户端的地址信息,这个参数可以设置为NULL

addrlen  :  这是一个指向socklen_t类型的指针,用于存储addr结构体的长度。

  

如果连接成功建立,则返回新创建的套接字的描述符。

如果发生错误,则返回-1,并设置相应的错误码。

connect  (  )  函数  : 

客户端向服务器发起连接请求。

#include < sys/types.h >

#include < sys/socket .h >

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

// 参数说明

sockfd  :   套接字

addr    :     指向套接字地址结构的指针,它包含了要绑定的IP地址和端口号。

addrlen  :   这是一个指向socklen_t类型的指针,用于存储addr结构体的长度。

当调用connect()函数时,它会尝试与指定的服务器建立连接。

如果连接成功建立,函数返回0;

如果连接失败,返回-1,并设置相应的错误码。

出错处理函数 : 

perror ( )函数 :

用于输出上一个系统调用失败时的错误描述信息。

#include < stdio.h >

#include < errno.h >

void  perror ( const  char  *s)  ;

// 例如

perror ( " connect failed " );  

法二  :  使用 fprintf ()  

它通常用于输出程序运行过程中的错误信息。与stdout(标准输出)不同,stderr的输出通常会被送到终端窗口。

fprintf( stderr, "error message :%s \n", strerror(errno) )


// strerror ()   获取错误描述

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

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

相关文章

传输线的阻抗和反射到底是什么关系?

传输线的阻抗和反射到底是什么关系? 传输线是通信系统中最基本的传输元件之一&#xff0c;它可以将信号从一个端点传输到另一个端点。然而&#xff0c;在实际的通信系统中&#xff0c;传输线往往面临着许多问题&#xff0c;其中最主要的两个问题是阻抗不匹配和信号反射。本文将…

zabbix监控安装-linux

zabbix6.4中文文档1. 简介 (zabbix.com) Zabbix 是一个企业级的开源分布式监控解决方案。 1.zabbix结构体系 Server&#xff1a; server 是存储所有配置、统计和操作数据的中央存储库。 Proxy&#xff1a; zabbix proxy可以代替 Zabbix server 收集性能和可用性数据。p…

linux的美化工具 oh-my-zsh的安装与使用 神器工具

目录 1 安装zsh的环境2 安装 Oh My Zsh3 主题设置重新启动终端:关闭连接 在重新链接一下附加 -插件管理案例讲解看效果 Oh My Zsh 是一款基于 Zsh 的开源命令行工具&#xff0c;它提供了丰富的主题和插件&#xff0c;可以帮助用户更加高效地使用终端。本文将详细介绍 Oh My Zsh…

【StringBuilder和StringBuffer】

文章目录 StringBuilder和StringBufferString类、StringBuilder和StringBuffer的区别 StringBuilder和StringBuffer的区别StringBuilder 字符串逆置 StringBuilder和StringBuffer String类、StringBuilder和StringBuffer的区别 String类的特点是不可变性&#xff0c;所以Stri…

Android项目升级到AndroidX

1、 2、 然后报错了&#xff1a; The gradle plugin version in your project build.gradle file needs to be set to at least com.android.tools.build:gradle:3.2.0 in order to migrate to AndroidX. 修改gradle版本 31报错了就用30.0.0了 3、 提示备份、然后执行do re…

软文发布如何选择对应的媒体

企业做软文推广第一步&#xff0c;就是选择合适的媒体进行投放&#xff0c;然而许多企业不知道如何选择合适的媒体导致推广工作十分被动&#xff0c;无法取得效果&#xff0c;今天媒介盒子就来和大家分享&#xff0c;企业应该如何选择对应的媒体。 一、 媒体类型 根据软文类型…

视频集中存储EasyCVR平台播放一段时间后出现黑屏是什么原因?该如何解决?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

有关环境变量

什么是环境变量 用户变量仅对当前用户有效&#xff0c;系统变量对整个系统有效 环境变量就是一个字符串&#xff0c;为了方便修改给隔开了&#xff08;图形化界面&#xff09; 环境变量可以用来配置路径&#xff0c;也可以用来配置其他&#xff0c;比如图中的 NUMBER_OF_PROC…

医院陪诊小程序源码 医院陪诊陪护系统源码

医院陪诊小程序源码 医院陪诊陪护系统源码 陪诊系统小程序&#xff1a;提高陪诊效率&#xff0c;改善医疗服务体验 近年来&#xff0c;随着互联网技术的不断发展&#xff0c;我们的生活中出现了越来越多的智能设备和智能应用&#xff0c;这些智能应用不仅极大方便了我们的生活…

数据仓库工具箱-零售业务

文章目录 一、维度模型设计的4步过程1.1 第一步&#xff1a;选择业务过程1.2 第二步&#xff1a;声明粒度1.3 第三步&#xff1a;确定维度1.4 第四步&#xff1a;确定事实 二、零售业务案例研究2.1 第一步&#xff1a;选择业务过程2.2 第二步&#xff1a;声明粒度2.3 第三步&am…

AI智能客服代替IVR

什么是IVR导航&#xff1f; “欢迎致电XXX客服热线 XXX请按1 XX服务请按2 重听请按3 人工服务请按0 返回请按*号键” 这个导航称为语音导航IVR。传统的电话通道系统通过电话上的按钮广播语音信息来通知客户或等待客户输入内容&#xff0c;然后根据客户的输入进行下一步的…

webgoat-client side客户端问题

client side Bypass front-end restrictions 用户对 Web 应用程序的前端有很大程度的控制权。 它们可以更改 HTML 代码&#xff0c;有时也可以更改脚本。这就是为什么 需要特定输入格式的应用也应在服务器端进行验证&#xff0c;而不是只在前端做限制。 0x02 先提交请求&am…

技术分享 | 想做App测试就一定要了解的App结构

app 的结构包含了 APK 结构和 app 页面结构两个部分 APK结构 APK 是 Android Package 的缩写&#xff0c;其实就是 Android 的安装包。通过将 APK 文件直接传到 Android 模拟器或 Android 手机中执行即可安装。 APK 文件其实是 zip 格式&#xff0c;但后缀名被修改为 apk&am…

虚幻引擎:如何在工程里面添加插件

1.在自己的项目中安装插件 在content目录下创建一个Plugins的文件,将插件文件放进去即可 2.在软件上安装,这样所有创建的项目都会带有此插件 将插件放在自己软件的这个目录下就好了

【JavaSE】基础笔记 - 类和对象(下)

目录 1、this引用 1.1、为什么要有this引用 1.2、什么是this引用 1.3、 this引用的特性 2、 对象的构造及初始化 2.1、 如何初始化对象 2.2、构造方法 2.2.1、概念 2.2.2、特性 2.3、默认初始化 2.4、就地初始化 上篇&#xff1a;【JavaSE】基础笔记 - 类和对象&#…

拥抱电大新时代,助力学业攀升——广东开放大学电大搜题微信公众号助您一臂之力

随着信息时代的快速发展和教育的普及化&#xff0c;广东开放大学作为一所以开放教育为主要特色的学府&#xff0c;致力于为更多渴望进修和提升自己的学子们提供良好的学习环境和便捷的学习工具。在这个日新月异的时代&#xff0c;我们尽力拓宽学生学习的途径&#xff0c;让学子…

京东数据分析(京东销量):2023年9月京东投影机行业品牌销售排行榜

鲸参谋监测的京东平台9月份投影机市场销售数据已出炉&#xff01; 根据鲸参谋电商数据分析平台的相关数据数据显示&#xff0c;9月份&#xff0c;京东平台投影机的销量为13万&#xff0c;环比下滑约17%&#xff0c;同比下滑约25%&#xff1b;销售额将近2.6亿&#xff0c;环比下…

左孩子右兄弟

左孩子右兄弟 - 蓝桥云课 (lanqiao.cn) 这个题讲解一下思路。 看图 把样例转为二叉树&#xff1a; 我们可以发现所谓左孩子右兄弟就是说把一个节点的所有孩子节点中选取一个作为左子节点&#xff0c;这个节点的剩余孩子节点依次链接在这个左孩子节点的右边&#xff0c;直到某…

【送书福利-第二十五期】《AI时代系列书籍》

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主、前后端开发、人工智能研究生。公粽号&#xff1a;程序员洲洲。 &#x1f388; 本文专栏&#xff1a;本文…

python零基础扫盲02基础知识

02 2.1.1注释规则 2.1.2代码缩进 2.1.3编码规范 2.2.1保留字与标识符 2.2.2理解python中的变量 2.3.1数字 2.3.2字符串 2.3.3布尔类型 2.3.4数据类型转换 2.4.1使用input&#xff08;&#xff09;函数输入 2.4.2使用print&#xff08;&#xff09;函数输出