后端开发|php教程
TCP,UDP,socket
后端开发-php教程
php网络直播聊天室源码,vscode 极客,ubuntu exec,tomcat缓存配重,sqlite事务回滚处理,地图插件源代码如何加入到html中,从浏览器判断前端框架,如何在chrome执行爬虫脚本,php生成签名,seo电脑怎么打开,.net酒店网站源码,静态网页能连接数据库吗,dz模板不是正版lzw
学习LInux,网络编程套接字是基础,也是新手学习的难点,通过本篇文章,读者可以通过图解、作者的代码实现思路全面理解IP地址、端口号、TCP、UDP概念、socket API用法、模拟客户端/服务器通信等。
vc dx截图 源码,ubuntu桥接地址,tomcat两大组件,数据爬虫校验,小程序调用php,seo搜索推广找行者SEOlzw
Mark:阅读blog + 代码实现耗时18分钟
php电子产品网站源码,ubuntu g95,爬虫资金流向,paseurl php,白话叙述seolzw
文章重点:
IP地址、端口号……
socket API
实现UDP客户端/服务器
套接字是网络编程中的一种通信机制,是支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。
前面介绍过,本地的进程间通信(IPC)有很多种方式,常见的总结以下几点:
1、管道(包括无名管道和命名管道); 2、消息队列; 3、信号量; 4、共享存储。 5、……( Socket和Streams支持不同主机上的两个进程IPC)。
认识网络层通信过程:
初识IP:
(IP就是:Internet协议IP)
端口号:
端口号(port)是传输层协议的内容。
端口号是一个2字节16位的整数;
端口号用来标识一个进程,告诉操作系统,当前这个数据交给哪一个程序进行解析;
IP地址 + 端口号能标识网络上的某一台主机的某一个进程;
一个端口号只能被一个进程占用。
端口号 & 进程:
概念源端口号 & 目的端口号
TCP:
(TCP)传输控制协议,面向连接。是一种提供可靠数据传输的通用协议。
传输层协议
有连接
可靠传输
面向字节流
UDP:
(UDP)用户数据报协议,是一个面向无连接的协议。采用该协议不需要两个应用程序先建立连接。UDP协议不提供差错恢复,不能提供数据重传,因此该协议传输数据安全性差。
传输层协议
无连接
不可靠传输
面向数据报
网络字节序:
如何定义网络数据流的地址?
其实很容易理解这个问题,就是C语言中比较讲究的大小端问题。
发送机按内存地址从低到高顺序发送;
接收主机按内存地址从低到高顺序保存;
TCP/IP规定:网络数据流应采用大端字节序,即地地址高字节;
不论主机是大端机还是小端机,都必须遵循TCP/IP规定;
如果发送机是小端,就先将数据转成大端再发送。
socket API:
//创建socket文件描述符 (TCP/UDP,客户端+服务器)int socket(int domain, int type, int protocol);
//绑定端口号 (TCP/IP,服务器)int bind(int socket, const struct sockaddr *address, socklen_t address_len);
//开始监听socket (TCP,服务器)int listen(int socket, int backlog);
//接受请求 (TCP,服务器)int accept(int socket, struct sockaddr* address, socklen_t* address_len);
//建立连接 (TCP,客户端)int connect(int sockfd, const struct struct sockaddr *addr, aocklen_t addrlen);
//关闭套接字int close(int fd);
简单的TCP网络程序:
TCP客户—服务器程序的执行流程图:
服务器代码:
#include#include#include#include#include#include#includeusing namespace std;#define SERVER_PORT 5050//端口号#define SERVER_IP "192.168.3.254" //服务器ip#define QUEUE_SIZE 5 //所监听端口队列大小int main(int argc, char *argv[]){ //创建一个套接字,并检测是否创建成功 int sockSer; sockSer = socket(AF_INET, SOCK_STREAM, 0); if(sockSer == -1){ perror("socket"); } //设置端口可以重用,可以多个客户端连接同一个端口,并检测是否设置成功 int yes = 1; if(setsockopt(sockSer, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){ perror("setsockopt"); } struct sockaddr_in addrSer,addrCli; //创建一个记录地址信息的结构体 addrSer.sin_family = AF_INET; //所使用AF_INET协议族 addrSer.sin_port = htons(SERVER_PORT);//设置地址结构体中的端口号 addrSer.sin_addr.s_addr = inet_addr(SERVER_IP); //设置其中的服务器ip //将套接字地址与所创建的套接字号联系起来。并检测是否绑定成功 socklen_t addrlen = sizeof(struct sockaddr); int res = bind(sockSer,(struct sockaddr*)&addrSer, addrlen); if(res == -1) perror("bind"); listen(sockSer, QUEUE_SIZE); //监听端口队列是否由连接请求,如果有就将该端口设置位可连接状态,等待服务器接收连接 printf("Server Wait Client Accept......\n"); //如果监听到有连接请求接受连接请求。并检测是否连接成功,成功返回0,否则返回-1 int sockConn = accept(sockSer, (struct sockaddr*)&addrCli, &addrlen); if(sockConn == -1) perror("accept"); else { printf("Server Accept Client OK.\n"); printf("Client IP:> %s\n", inet_ntoa(addrCli.sin_addr)); printf("Client Port:> %d\n",ntohs(addrCli.sin_port)); } char sendbuf[256]; //申请一个发送缓存区 char recvbuf[256]; //申请一个接收缓存区 while(1) { printf("Ser:>"); scanf("%s",sendbuf); if(strncmp(sendbuf,"quit",4) == 0) //如果所要发送的数据为"quit",则直接退出。 break; send(sockConn, sendbuf, strlen(sendbuf)+1, 0); //发送数据 recv(sockConn, recvbuf, 256, 0); //接收客户端发送的数据 printf("Cli:> %s\n",recvbuf); } close(sockSer); //关闭套接字 return 0;}
客户端代码:
#include#include#include#include#include#include#includeusing namespace std;#define SERVER_PORT 5050#define SERVER_IP "192.168.3.254"int main(int argc, char *argv[]){ //创建客户端套接字号,并检测是否创建成功 int sockCli; sockCli = socket(AF_INET, SOCK_STREAM, 0); if(sockCli == -1) perror("socket"); //创建一个地址信息结构体,并对其内容进行设置 struct sockaddr_in addrSer; addrSer.sin_family = AF_INET; //使用AF_INET协议族 addrSer.sin_port = htons(SERVER_PORT); //设置端口号 addrSer.sin_addr.s_addr = inet_addr(SERVER_IP); //设置服务器ip bind(sockCli,(struct sockaddr*)&addrCli, sizeof(struct sockaddr)); //将套接字地址与所创建的套接字号联系起来 //创建一个与服务器的连接,并检测连接是否成功 socklen_t addrlen = sizeof(struct sockaddr); int res = connect(sockCli,(struct sockaddr*)&addrSer, addrlen); if(res == -1) perror("connect"); else printf("Client Connect Server OK.\n"); char sendbuf[256];//申请一个发送数据缓存区 char recvbuf[256];//申请一个接收数据缓存区 while(1) { recv(sockCli, recvbuf, 256, 0); //接收来自服务器的数据 printf("Ser:> %s\n",recvbuf); printf("Cli:>"); scanf("%s",sendbuf); if(strncmp(sendbuf,"quit", 4) == 0) //如果客户端发送的数据为"quit",则退出。 break; send(sockCli, sendbuf, strlen(sendbuf)+1, 0); //发送数据 } close(sockCli); //关闭套接字 return 0;}
简单的UDP网络程序:
相对与TCP来说,UDP安全性差,面向无链接。所以UDP地实现少了连接与接收连接的操作。所以在收发数据时就不能再用send()和recvfrom()了,而是用sendto()和recvto()之名从哪收发数据。
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
服务器端代码:
#include#include#include#include#include#includeint main(){ //创建一个套接字,并检测是否创建成功 int sockSer = socket(AF_INET, SOCK_DGRAM, 0); if(sockSer == -1) perror("socket"); struct sockaddr_in addrSer; //创建一个记录地址信息的结构体addrSer.sin_family = AF_INET; //使用AF_INET协议族addrSer.sin_port = htons(5050);//设置地址结构体中的端口号 addrSer.sin_addr.s_addr = inet_addr("192.168.3.169"); //设置通信ip //将套接字地址与所创建的套接字号联系起来,并检测是否绑定成功 socklen_t addrlen = sizeof(struct sockaddr); int res = bind(sockSer,(struct sockaddr*)&addrSer, addrlen); if(res == -1) perror("bind"); char sendbuf[256]; //申请一个发送数据缓存区 char recvbuf[256]; //申请一个接收数据缓存区 struct sockaddr_in addrCli; while(1) { recvfrom(sockSer,recvbuf,256,0,(struct sockaddr*)&addrCli, &addrlen);//从指定地址接收客户端数据 printf("Cli:>%s\n",recvbuf); printf("Ser:>"); scanf("%s",sendbuf); sendto(sockSer,sendbuf,strlen(sendbuf)+1,0,(struct sockaddr*)&addrCli, addrlen); //向客户端发送数据 } return 0;}
客户端代码:
#include#include#include#include#include#includeint main(){ //创建一个套接字,并检测是否创建成功 int sockCli = socket(AF_INET, SOCK_DGRAM, 0); if(sockCli == -1){ perror("socket"); } addrSer.sin_family = AF_INET; //使用AF_INET协议族addrSer.sin_port = htons(5050);//设置地址结构体中的端口号 addrSer.sin_addr.s_addr = inet_addr("192.168.3.169"); //设置通信ip socklen_t addrlen = sizeof(struct sockaddr); char sendbuf[256]; //申请一个发送数据缓存区 char recvbuf[256]; //申请一个接收数据缓存区 while(1){ //向客户端发送数据 printf("Cli:>"); scanf("%s",sendbuf); sendto(sockCli, sendbuf, strlen(sendbuf)+1, 0, (struct sockaddr*)&addrSer, addrlen); 接收来自客户端的数据 recvfrom(sockCli, recvbuf, BUFFER_SIZE, 0, (struct sockaddr*)&addrSer, &addrlen); printf("Ser:>%s\n", recvbuf); } return 0;}
【推荐课程:TCP/IP视频教学】
如果觉得《socket套接字详解(TCP与UDP)》对你有帮助,请点赞、收藏,并留下你的观点哦!