网站空间空间租赁,京东云免费建wordpress,中山技术支持中山网站建设,企业管理软件管理系统讲解 网络基础知识网络编程tcp编程流程图示理解bind和accept函数理解监视套接字和链接套接字理解linux和window下的编程实现tcp特点 udp编程流程图示理解udp特点 http编程流程图示理解编程实现-网站服务器 网络基础知识
OSI分层#xff1a;应用层 表示层 会话层 传输层 网络层… 讲解 网络基础知识网络编程tcp编程流程图示理解bind和accept函数理解监视套接字和链接套接字理解linux和window下的编程实现tcp特点 udp编程流程图示理解udp特点 http编程流程图示理解编程实现-网站服务器 网络基础知识
OSI分层应用层 表示层 会话层 传输层 网络层 数据链路层 物理层 tcp/ip: 应用层 传输层 网络层 数据链路 ip地址唯一标识一台主机 ipv4 32位 ipv6 128位 寻址 可以反映物理上的一个变化 MAC地址48 固化在计算机中 ip地址又两部分构成网络号主机号 端口号标识一个应用程序的代号 短整型 协议共同遵守的约定 tcp协议 网络中的规则 ip , http/https,/ftp, tcp/ ipv4头部结构 4位头部长度表示15行 每行4字节就是60字节 减去 基本的20字节 剩余的选项 40字节 TCP头部结构
剩余的选项仍然是 40字节 应用程序传递数据的一个过程 tcp协议 这四层应用层 传输层 网络层 数据链路 ip地址由网络号和主机号共同构成的
129.168.1.1点分十进制转化为 无符号整型 unsignal int inet_addr(); 无符号整型转化为点分十进制 inet_ntoa(); 每一个字节8位 都是十进制转化的最后将四个字节组合在一起变成一个无符号整型
大端网络字节序列 htons() 地址ipport
表示Ipv4的地址结构
struct socketaddr_in ipv4;通用的套接字地址
struct socketaddr;套接字 像手机一样进行数据的收发
需要让服务器先运行起来客户端主动连接服务器所以服务器需要把自己的ip 和端口告诉客户端
在Windows下查看ip地址
ipconfigLinux下查看虚拟机ip地址
ifconfig判断两个主机是否连通
ping 无法访问目标主机 说明该网络下没有这个主机 请求超时可能有防火墙 没有成功
网络编程
tcp编程流程
图示理解
tcp服务器 客户端编程流程
bind和accept函数理解
bind就是看看saddr得ip地址端口有没有问题ip地址是不是写错了端口是不是被占用了如果没有问题就将表示符合该地址绑定取名成功
int c accept(sockfd, (struct sockaddr *)caddr, len);服务器会在该行阻塞等待用户端的连接一旦connect成功阻塞结束得到新的描述符c该c对应刚才的客户端类似一个链接每个c都对应一个客户端表示一条链接。
监视套接字和链接套接字理解
监听套接字 都是这一个 类似文件描述符 在一个进程中fd都是3 不变 链接套接字一个链接 由于服务器012 被占用 监视套接字是3 所以链接套接字从4开始说明一个客户端和服务器链接上了如果另一个客户端链接那就是5 … 如果不理解可以看这篇文章讲的挺通俗易懂的 监视套接字和链接套接字
int c accept(sockfd,(struct sockaddr*) caddr,len);//阻塞 服务器刚开始是不知道客户端的地址的所以先 caddr 把结构体放这里等客户端根据服务器给的ip端口找到connect此时accept接收这个时候就知道了客户端的地址和ip存储在caddr
为什么c变成了4 原来的sockfd是3 而客户端的sockfd一直是3 类似用你的手机3给10086电话你的电话号不变一直是3 服务器类似一个服务中心服务器刚开始也是10086 即3号手机接收接听到了一个用户就转接到另一个人工客服接听即4 号手机原来的3号手机继续接听客户的电话。一次类推。
linux和window下的编程实现
ser.c
#include stdio.h
#include stdlib.h
#include unistd.h
#include string.h
#include sys/socket.h
#include netinet/in.h
#include arpa/inet.hint main()
{int sockfd socket (AF_INET,SOCK_STREAM,0);if(sockfd -1){exit(1);}struct sockaddr_in saddr, caddr;memset(saddr,0,sizeof(saddr));saddr.sin_family AF_INET;saddr.sin_port htons(6000);saddr.sin_addr.s_addr inet_addr(192.168.1.49);//“127.0.0.1”int res bind(sockfd,(struct sockaddr*)saddr,sizeof(saddr));if ( res -1){printf(bind err\n);exit(1);}res listen(sockfd,5);if ( res -1 ){exit(1);}while( 1 ){socklen_t len sizeof(caddr);int c accept(sockfd,(struct sockaddr*) caddr,len);//阻塞if ( c 0 ){continue;}printf(accept c%d\n,c);char buff[128] {0};int n recv(c,buff,127,0);//阻塞printf(buff%s\n,buff);send(c,ok,2,0);close(c);}
}cli.c
#include stdio.h
#include stdlib.h
#include unistd.h
#include string.h
#include sys/socket.h
#include netinet/in.h
#include arpa/inet.hint main()
{int sockfd socket(AF_INET,SOCK_STREAM,0);if ( sockfd -1){exit(1);}struct sockaddr_in saddr;memset(saddr,0,sizeof(saddr));saddr.sin_family AF_INET;saddr.sin_port htons(6000);saddr.sin_addr.s_addr inet_addr(192.168.1.49);int res connect(sockfd,(struct sockaddr*)saddr,sizeof(saddr));if ( res -1){printf(connect err\n);exit(1);}send(sockfd,hello,5,0);char buff[128] {0};recv(sockfd,buff,127,0);//okprintf(buff%s\n,buff);close(sockfd);
}Windows系统上的服务器和客户端
//window servier
#if 0
//ConsoleApptcp.cpp : 此文件包含 main 函数。程序执行将在此处开始并结束。
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include stdio.h
#include stdlib.h
#include sys/types.h
#include WinSock2.h //网络头文件
#include string.h
#include ws2tcpip.h //socklen_t
#include iostreamusing namespace std;
#pragma comment(lib, ws2_32.lib) //网络库文件//初始化网络库
void InitNetwork() {WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested MAKEWORD(2, 2);err WSAStartup(wVersionRequested, wsaData);if (err ! 0){return;}}int main()
{InitNetwork();SOCKET sockfd socket(AF_INET, SOCK_STREAM, 0);if (sockfd INVALID_SOCKET){cout socket err endl;return 0;}struct sockaddr_in saddr;memset(saddr, 0, sizeof(saddr));saddr.sin_family AF_INET;saddr.sin_port htons(6000);//saddr.sin_addr.S_un.S_addr INADDR_ANY;saddr.sin_addr.S_un.S_addr inet_addr(192.168.1.32);//这个要用需要加宏定义//saddr.sin_addr.S_un.S_addr inet_pton(AF_INET,192.168.1.50,NULL);int res bind(sockfd, (SOCKADDR*)saddr, sizeof(saddr));if (res SOCKET_ERROR){cout bind err endl;return 0;}if (listen(sockfd, 5) SOCKET_ERROR){cout listen err endl;return 0;}while (true){//struct sockaddr_in caddr;SOCKADDR_IN caddr;socklen_t len sizeof(caddr);int c accept(sockfd, (SOCKADDR*)caddr, len);if (c INVALID_SOCKET){continue;}cout accept c c endl;char buff[128] { 0 };while (true){if (recv(c, buff, 127, 0) 0){break;}cout buff endl;send(c, ok, 2, 0);}closesocket(c);}}
#endif//windows client
#if 0
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include stdio.h
#include stdlib.h
#include sys/types.h
#include WinSock2.h //网络头文件
#include string.h
#include ws2tcpip.h //socklen_t
#include iostreamusing namespace std;
#pragma comment(lib, ws2_32.lib) //网络库文件//初始化网络库
void InitNetwork() {WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested MAKEWORD(2, 2);err WSAStartup(wVersionRequested, wsaData);if (err ! 0){return;}}int main()
{InitNetwork();SOCKET sockfd socket(AF_INET, SOCK_STREAM, 0);if (sockfd INVALID_SOCKET){cout socket err endl;return 0;}struct sockaddr_in saddr;memset(saddr, 0, sizeof(saddr));saddr.sin_family AF_INET;saddr.sin_port htons(6000);saddr.sin_addr.S_un.S_addr inet_addr(192.168.1.49);int res connect(sockfd, (struct sockaddr*)saddr, sizeof(saddr));if (res -1){cout connect err endl;closesocket(sockfd);WSACleanup();}while (true){cout input endl;char buff[128] { 0 };cin buff;if (strncmp(buff, end, 3) 0){break;}send(sockfd, buff, strlen(buff), 0);memset(buff, 0, 128);recv(sockfd, buff, 127, 0);cout buff endl;}closesocket(sockfd);WSACleanup();return 0;
}
#endiftcp特点 int n recv(c,buff,1,0);一次只收一个字符
当发送速度快会一起写到缓冲区然后一起发送数据太大会拆开发送 套接字有发送缓冲区和接收缓冲区
netstat应答确认 超时重传 乱序重拍 去重 滑动窗口控制 tcp特点 面向连接的 可靠的 流式服务
udp编程流程
图示理解 udp特点
无连接 不可靠 数据报服务 双方无连接服务器关了再起启动发送消息还是能收到在建立一个客户端也可以发送信息。 udp发送数据时要保证数据收完否则其他数据就丢了 严格的一对一发几次收几次
一个端口可以被一个套接字绑定可以绑定两个是协议不同 tcp在应用层面不丢数据底层会丢网络层丢了重发就行tcp自身保证其可靠性 tcp适合传文件 丢一个字节都不行 udp适合视频通话 丢包就是卡了
http编程流程
图示理解 应用层 http 浏览器和服务器之间的通讯 传输层 tcp
两次以上的请求复用了同一个tcp连接就是长连接 http用80号端口 https用443号端口 小于1024的端口需要管理员才能访问 后面有\r\n结束 最后一行还有一个\r\n content_length 不包含报头 服务器收到浏览器的信息放到buff数组里服务器知道了浏览器想访问的资源就是index.html,服务器需要做的是找到该资源发给浏览器就行 浏览器会自己发起一个请求去访问图标 这是一组请求可能会有多次请求在一次点击的过程中
编程实现-网站服务器
myhttp.c
#include stdio.h
#include stdlib.h
#include unistd.h
#include string.h
#include sys/socket.h
#include netinet/in.h
#include arpa/inet.h
#include pthread.h
#includefcntl.h
#define PATH /home/ittao/code/day17
int socket_init();
char *get_filename(char buff[])
{if(buffNULL){return NULL;}char *ptrNULL;char*sstrtok_r(buff, ,ptr);if(sNULL){return NULL;}printf(way:%s\n,s);sstrtok_r(NULL, ,ptr);return s;
}
void *thread_fun(void *arg)
{int c (int)arg;while (1){char buff[4096] {0};int n recv(c, buff, 4095, 0);if(n0){break;}printf(buff:%s\n, buff);char*filenameget_filename(buff);if(filenameNULL){send(c,http err:404,12,0);break;}printf(filename:%s\n,filename);char path[256]{PATH};if(strcmp(/,filename)0){strcat(path,/index.html);}else{strcat(path,filename);}int fdopen(path,O_RDONLY);if(fd-1){send(c, http err:404, 12, 0);}int filesizelseek(fd,0,SEEK_END);lseek(fd,0,SEEK_SET);char http_head[256]{ my HTTP/1.1 200 OK\r\n};strcat(http_head,Server:myhttp\r\n);sprintf(http_headstrlen(http_head),Content-Length:%d\r\n,filesize);strcat(http_head,\r\n);send(c,http_head,strlen(http_head),0);char data[1024];int num0;while((numread(fd,data,1024))0){send(c,data,num,0);}close(fd);}close(c);printf(client close\n);pthread_exit(NULL);
}
int accept_client(int sockfd)
{struct sockaddr_in caddr;int len sizeof(caddr);int c accept(sockfd, (struct sockaddr *)caddr, len);return c;
}
int main()
{int sockfd socket_init();if (sockfd -1){exit(1);}while (1){int caccept_client(sockfd);if (c ! -1){pthread_t id;pthread_create(id, NULL, thread_fun, (void *)c);} }
}
int socket_init()
{int sockfd socket(AF_INET, SOCK_STREAM, 0);if (sockfd -1){return -1;}struct sockaddr_in saddr;memset(saddr, 0, sizeof(saddr));saddr.sin_family AF_INET;saddr.sin_port htons(80);saddr.sin_addr.s_addr inet_addr(192.168.1.49);int res bind(sockfd, (struct sockaddr *)saddr, sizeof(saddr));if (res -1){printf(bind err\n);return -1;}res listen(sockfd, 5);if (res -1){return -1;}return sockfd;
}