5.5中介绍了内存调试的相关信息,其中5.5.4(P176)介绍了相关工具--Valgrind的安装已经使用 ,目前暂时还没有阅读,直接调到了网络那部分,后面有需要再进行阅读。
第六章 计算机网络:
ISO提出的七层网络模型以方便计算机能够更方便且大范围的相互通信:
需要传输数据时,各层会在数据(data)前加上报头,数据链路层还会额外加上报尾,这应该就是封装,解封装的流程则是倒过来的,每层不是加报头报尾,而是去除:
TCP全称:传输控制协议 (Transmission Control Protocol)
TCP头格式:
其中,16位的端口号的作用是:确认身份
序号值用于确定传输数据所在地址
当出现异常情况导致数据传输失败,会进行超时重传
计算公式在P199上,但是这种计算方式遇到需要重传的情况会产生二义性,为了解决这一个问题,提出了一种
6.1.5 TCP滑动窗口 主要有两个作用 一是提供TCP的可靠性,二是提供TCP的流控(流量控制)特性->即通过控制滑动窗口的大小来控制流量。
6.16 TCP拥塞控制
1.慢开始和拥塞避免
2.快重传和快恢复
6.2 TCP网络编程API
TCP/IP协议中网络层的IP地址可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序。用这三种信息即可标识网络进程,进而可以进行通信.
socket(套接字):
6.3 实现一个TCP Seiver
client.cpp:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<arpa/inet.h>
#define MAXLINE 4096
int main(int argc,char** argv){
int sockfd,n;
char recvline[4096],sendline[4096];
struct sockaddr_in servaddr;
if(argc !=2){
printf("usage: ./client <ipaddress>\n");
return 0;
}
if((sockfd = socket(AF_INET,SOCK_STREAM,0))<0){
printf("create socket error:%s(errno:%d)\n",strerror(errno),errno);
return 0;
}
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(6666);
if(inet_pton(AF_INET,argv[1],&servaddr.sin_addr)<=0){
printf("inet_pton error for %s\n",argv[1]);
return 0;
}
if(connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0){
printf("connect error:%s(erron:%d)\n",strerror(errno),errno);
return 0;
}
printf("send msg to server :\n");
fgets(sendline,4096,stdin);
if(send(sockfd,sendline,strlen(sendline),0)<0){
printf("send msg error :%s(errrno:%d)\n",strerror(errno),errno);
return 0;
}
close(sockfd);
return 0;
}
server.cpp:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#define MAXLINE 4096
int main(int argc,char** argv){
int listenfd , connfd;
struct sockaddr_in servaddr;
char buff[4096];
int n;
if((listenfd = socket(AF_INET,SOCK_STREAM,0))==1){
printf("creat socker error:%s(errno:%d)",strerror(errno),errno);
return 0;
}
memset(&servaddr , 0 ,sizeof(servaddr));
servaddr.sin_family = AF_INET;
//127.0.0.1 ->127:01111111,0:00000000,0:00000000,1:00000001 =>01111111000000000000000000000001=>01111111|00000000|00000000|00000001=>2130706433 主机字节序
servaddr.sin_addr.s_addr = htonl(2130706433);
servaddr.sin_port = htons(6666);
if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr))==-1){
printf("bind socket error:%s(error:%d)\n",strerror(errno),errno);
return 0;
}
if(listen(listenfd,10)==-1){
printf("listen socket errotr :%s(errno:%d)\n",strerror(errno),errno);
return 0;
}
printf("======================= wait for client request ===========================");
while (1)
{
if((connfd = accept(listenfd,(struct sockaddr*)NULL,NULL))==-1){
printf("accept socket error:%s(errno:%d)",strerror(errno),errno);
continue;
}
n = recv (connfd,buff,MAXLINE,0);
buff[n]='\0';
printf("recv msg from client :%s\n",buff);
close(connfd);
}
close(listenfd);
return 0;
}
makefile:
all::server client
server:server.o
g++ -g -o server server.o
client:client.o
g++ -g -o client client.o
server.o:server.cpp
g++ -g -c server.cpp
client.o:client.cpp
g++ -g -c client.cpp
clean:all
rm all
注意,server.cpp中 servaddr.sin_addr.s_addr = htonl(2130706433);这行代码原书中用的是servaddr.sin_addr.s_addr = htonl(INADDR_ANY );,即任何ip地址都可以链接到服务器,可以将其改成任意ip地址以实现私密链接
数据转化方式参考:socket编程(C++)报错 'inet_addr': Use inet_pton() or InetPton() instead or define _WIN以及引起的知识整理-CSDN博客