热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

c/c++开发分享【网络编程01】socket的基础知识简单网络通信程序

1.什么是socketsocket(套接字),简单来说是IP地址与端口(port)的组合,可以与远程主机的应用程序进行通信。通过IP地址可以确定一台主机,而通过端口则可以确定某一个

1.什么是socket

  socket(套接字),简单来说是ip地址与端口(port)的组合,可以与远程主机的应用程序进行通信通过ip地址可以确定一台主机,而通过端口则可以确定某一个应用程序。ip+端口则可以完全确定某台主机的某个应用。socket起源于unix,类似一种特殊文件,可以进行打开,关闭,读写操作。总而言之,有了socket就可以与网络上的主机进行通信。

2.tcp/udp 协议

  要进行网络通信,就要进行一定规则约束,tcp/udp就是这样的协议,规定了通信的规则。

  tcp是可靠的,面向连接的双向数据传输协议。可靠是指数据不会重复,也不会丢失。每当发送方发送一个数据给接收方时,如果接收方接收到了该数据,则会发送确认信息给发送方表示”我已经收到该数据了,你可以发送下一条数据了“,收到确认信息后,发送方才会发送下一条数据。这样就可以确定信息的无误。双向传输指双方都可以作为发送方或接收方。

  udp是不可靠的,无连接的双向传输协议。udp协议只管发送数据,不会确认你有没有收到,只负责发,不负责确认,所以是不可靠的。udp适用于传输视频之类的,视频就算丢失一两帧也不会有太大影响。

  socket既可以是基于tcp,也可以是基于udp的,根据需求选择即可。

 

3.一个简单的通信程序

  用一个简单的例子来说明socket的用法。用socket写的程序一般分为,两部分,一个是服务器端,一个是客户端.

  下面说明务器端创建过程

  1).首先要有套接字才能进行通信,创建套接字的函数是

 

1 int socket(int af, int type, int protocol);

  af:表示地址族,常用的有af_inet表示使用ipv4地址,af_inet6表示使用ipv6地址

  type:传输类型常用有sock_stream ,sock_dgram,流式传输,报文传输

  protocol:要使用的协议常用有 ipproto_tcp 和 ipptoto_udp,分别表示tcp,udp协议

  返回一个套接字描述符,也就是一个整型。

  2).用bind()函数确定socket各种属性

1 int bind(int sock, struct sockaddr *addr, socklen_t addrlen);  

  sock:要绑定的套接字

  addr:sockaddr地址结构体,里面包含使用的协议,ip地址,端口等。要自己设定

  addrlen:sockaddr的大小,可以用sizeof()获取

  下面的代码展示创建一个套接字与绑定的过程

1 //使用ipv4地址,tcp协议 2 serversocket = socket(af_inet, sock_stream, ipproto_tcp); 3 sockaddr_in addr; 4 addr.sin_addr.s_un.s_addr = htonl(addr_any);//表示任何的ip过来连接都接受 5 addr.sin_family = af_inet;//使用ipv4地址 6 addr.sin_port = htons(6666);//使用6666号端口 7 bind(serversocket, &addr, sizeof(sockaddr));//将套接字与端口6666,设定接收的ip绑定

 3).listen函数监听

  设定属性后,服务器端就可以开始监听了,监控是否有客户端请求连接。

  函数原型

1 int listen(int sock, int backlog); 

  sock:套接字

  backlog:允许多少个客服端连接

 4).accept函数等待连接

  accept是一个阻塞函数,如果没有客户端清求连接会一直等待在这里

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

  sock:套接字,

  addr:sockaddr 结构体

  addrlen:addr的长度,可以用sizeof求到

  要注意该函数的返回值,它会返回一个新的套接字,这个新的套接字是用来与客户端通信的套接字,之前那个套接字是监听的套接字,要分清楚。

  5).send/recv发送/接收信息

  与客户端连接成功后就可以进行通信了。可以通信的函数有write/read,send/recv等,这里介绍send/recv

1 int send(int sockfd, const char *buf, size_t len, int flags); 2  3 int recv(int sockfd, char*buf, size_t len, int flags);

  sockfd:套接字

  buf:发送数据的缓冲区

  len:发送数据的长度

  flags:标志,一般为零

  6).closesocket函数关闭套接字

  closesocket()关闭套接字

  下面是一个完整的服务器端的代码

 1 #include  2 #include  3 #include  4 #pragma comment (lib,"ws2_32.lib")  5 int main()  6 {  7     socket serversocket;//监视的套接字  8     socket newsocket;//用来通信的套接字  9     sockaddr_in newaddr;//保存客户端的socket地址信息 10     sockaddr_in addr;//地址结构体,包括ip port(端口) 11  12     wsadata data;     13     word version;//socket版本 14     int info; 15     char buf[32];//数据缓冲区 16     /* 17        在使用socket之前要进行版本的设定和初始化 18        看不懂不用管 19     */ 20     version = makeword(2, 2);//设定版本 21     info = wsastartup(version, &data); 22     /*应用程序或dll只能在一次成功的wsastartup()调用之后 23            才能调用进一步的windows sockets api函数。 24         根据版本初始化 windows socket,返回0表示成功 25     */ 26  27     if (info != 0) 28     { 29         printf("初始化失败n"); 30         return -1; 31     } 32     if (lobyte(data.wversion) != 2 || hibyte(data.wversion) != 2) 33     {     34         printf("加载失败n"); 35         wsacleanup(); 36         return 0; 37     } 38      //创建套接字,使用tcp协议 39     serversocket = socket(af_inet, sock_stream, ipproto_tcp); 40     addr.sin_addr.s_un.s_addr = htonl(addr_any);//表示任何的ip过来连接都接受 41     addr.sin_family = af_inet;//使用ipv4的地址 42     addr.sin_port = htons(6666);//设定应用占用的端口 43     bind(serversocket, &addr, sizeof(sockaddr));//将套接字与端口6666,接收的ip绑定 44     listen(serversocket, 3);//开始监听,是否有客服端请求连接 45     printf("开始监听,等待连接..........n"); 46     int len = sizeof(sockaddr); 47     newsocket=accept(serversocket, (sockaddr*)&newaddr,&len); 48     sprintf(buf, "欢迎:%s 的用户连接", inet_ntoa(newaddr.sin_addr)); 49     send(newsocket, buf, 32, 0);//发送信息 50     printf("连接成功,开始发送信息..........n"); 51     recv(newsocket, buf, 32, 0);//接收信息 52     printf("接收到的信息为:%sn", buf); 53     closesocket(newsocket);//关闭套接字 54 }

  运行结果

  【网络编程01】socket的基础知识-简单网络通信程序

 

  客户端例子

  客户端与服务器端不同,服务器端是等待连接的,而客户端是主动连接的,所以客户端没有listen函数监听,也没有accept函数等待连接。

  客户端有一个connect函数用于主动连接服务器端。其余差不多

1 int connect(int sock, struct sockaddr *serv_addr, socklen_t addrlen);

  sock:套接字

  serv_addr:sockaddr结构体

  addrlen:serv_addr长度,可以用sizeof得到

  客户端代码

  

 1 #include  2 #include  3 #include  4 #pragma comment(lib,"ws2_32.lib")  5   6 int main()  7 {  8     socket clientsocket;  9     sockaddr_in addr; 10     int len; 11     char buf[32]; 12     int info; 13     wsadata data; 14     word version; 15     //设定版本,与初始化 16     version = makeword(2, 2); 17     info = wsastartup(version, &data); 18     if (info != 0) 19     { 20         printf("初始化失败n"); 21         return -1; 22     } 23     if (lobyte(data.wversion) != 2 || hibyte(data.wversion) != 2) 24     { 25         printf("加载失败n"); 26         wsacleanup(); 27         return 0; 28     } 29      30     clientsocket = socket(af_inet, sock_stream, 0);//创建套接字 31     //要连接的服务器的ip,因为现在服务器端就是本机,所以写本机ip 32     //127.0.0.1一个特殊的ip地址,表示是本机的ip地址 33     addr.sin_addr.s_un.s_addr = inet_addr("127.0.0.1"); 34     //端口要与服务器相同,不然找不到 35     addr.sin_port = htons(6666); 36     //用ipv4地址 37     addr.sin_family = af_inet; 38     //主动连接服务器 39     connect(clientsocket,(sockaddr*)&addr,sizeof(sockaddr)); 40     //接收服务发送的数据 41     recv(clientsocket, buf, 32, 0);//接收数据 42     printf("服务器发送的信息是:%sn", buf); 43     sprintf(buf, "%s","你好,服务器"); 44     //发送数据 45     send(clientsocket, buf, 32, 0); 46     //关闭套接字 47     closesocket(clientsocket); 48     return 0; 49  50 }

 

  先启动服务器,再启动客户端。一次简单的通信就完成了

     【网络编程01】socket的基础知识-简单网络通信程序 【网络编程01】socket的基础知识-简单网络通信程序

 

 

 

把这个简单的例子做出来,对于socket应该会有初步的认识,最起码应该学会怎么用。

下次利用socket写个简单的聊天程序,进一步加深对socket的认识。

 


推荐阅读
  • 本文介绍了在mac环境下使用nginx配置nodejs代理服务器的步骤,包括安装nginx、创建目录和文件、配置代理的域名和日志记录等。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • 【重识云原生】第四章云网络4.8.3.2节——Open vSwitch工作原理详解
    2OpenvSwitch架构2.1OVS整体架构ovs-vswitchd:守护程序,实现交换功能,和Linux内核兼容模块一起,实现基于流的交换flow-basedswitchin ... [详细]
  • 今天搭建了redis环境,使用自带的benchmark进行了性能测试选择测试键的范围大小默认情况下面,基准测试使用单一的key。在一个基于内存的数据库里,单一key测试和真实情况下 ... [详细]
  • python图书管理系统类_Python标准库socketserver使用线程混入实现异步TCP服务器
    推荐图书:《Python程序设计开发宝典》,ISBN:978-7-302-47210-0,董付国,清华大学出版 ... [详细]
  • Docker 快速入门指引
    本文最早发表于本人博客:Docker快速入门指引Docker是什么?Docker是Docker.Inc公司开源的一个基于LXC技术之上构建的Container容器引擎,基于Go语言 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • 安装oracle软件1创建用户组、用户和目录bjdb节点下:[rootnode1]#groupadd-g200oinstall[rootnode1]#groupad ... [详细]
  • Linux下ODBC安装配置
    Linux下ODBC安装配置ODBC原理ODBC是 ... [详细]
  • UML 包图
    什么是包包可直接理解为命名空间,文件夹,是用来组织图形的封装,包图可以用来表述功能组命名空间的组织层次。•在面向对象软件开发的视角中&#x ... [详细]
  • SpringBoot使用Netty实现远程调用的示例
    这篇文章主要介绍了SpringBoot使用Netty实现远程调用的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着 ... [详细]
author-avatar
小小鸟_--旺旺
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有