一, 建立连接三次握手成功然后拔掉服务器端网线重启服务器端,请分析服务器端和客户端的状态
服务器端:断网后关闭时要发送close无法发送报文段,重启之后只有一个监听套接字处于listen()状态; 客户端:通过客户端的命令来查看发现连接就是处于已完成三次握手状态,但是就是用不了
看书
二,UDP协议
特点:无连接 不可靠 数据报 能容忍丢数据就选择UDP否则选择TCP能选择UDP就说明我不在乎或者说这种丢数据的成本非常低 例如:下载3MB的数据必须全下载(TCP) 打视频卡了几秒() UDP时实性好比如说监控当下采集的数据当下发出去 TCP中间一丢就压时间重发就不好了 UDP网不好就丢包 追求可靠性如传输文件这种就用TCP 视频音频的实时性传播就是UDP 如果我传文件就要用UDP怎么办TCP可靠性的那些点自己去应用层实现类似的
TCP和UDP可以同时使用同一个端口并且可以同时运行 原因:UDP为无状态,收发数据时可以分清是哪个协议 同一个进程可以创建多个套接字(创建一个监听套接字和连接套接字既是客户端也是服务器端) 发出去就不管成功失败了,成功就成功失败就失败;
数据报 将服务端改为一次只收一个数据 比如我这个数据报有100个数据但你每次只收5个剩下的就会丢弃因为你只会收一次(一个数据报只能收一次)
1,服务器端代码
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
int main()
{
int sockfd=socket(AF_INET,SOCK_DGRAM,0);
assert(sockfd!=-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("127.0.0.1");
int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
assert(res!=-1);
while(1)
{
int len=sizeof(caddr);
char buff[128]={0};
recvfrom(sockfd,buff,127,0,(struct sockaddr*)&caddr,&len);
printf("buff=%s\n",buff);
sendto(sockfd,"ok",2,0,(struct sockaddr*)&caddr,sizeof(caddr));
}
}
2, 客户端代码
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
int main()
{
int sockfd=socket(AF_INET,SOCK_DGRAM,0);
assert(sockfd!=-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("127.0.0.1");
while(1)
{
char buff[128]={0};
fgets(buff,128,stdin);
if(strncmp(buff,"end",3)==0)
{
break;
}
sendto(sockfd,buff,strlen(buff)-1,0,(struct sockaddr*)&saddr,sizeof(saddr));
memset(buff,0,128);
int len=sizeof(saddr);
recvfrom(sockfd,buff,1276,0,(struct sockaddr*)&saddr,&len);
printf("buff=%s\n",buff);
}
close(sockfd);
}
三, http
http应用层协议,默认使用端口80 tcp:传输层协议 http短链接:浏览器发送请求,服务器端回复应答报文,后关闭 http长链接:发送回复在发送在回复,多次; 在浏览器中输入网址(域名),通过DNS将域名转为ip地址(也就是申请的服务器ip),然后三次我收简历连接,浏览器http请求报文,服务器回复应答报文 https更安全(加密)
请求方法
一般会问GET和POST哪个更安全(肯定选POST)
状态码
200OK代表成功
服务器端的代码(需要在看视频)
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<fcntl.h>
#define PATH "/home/stu/c219/day19"
int socket_init();
char*get_filename(char buff[]);
int main()
{
int sockfd=socket_init();
assert(sockfd!=-1);
while(1)
{
struct sockaddr_in caddr;
int len=sizeof(caddr);
int c=accept(sockfd,(struct sockaddr*)&caddr,&len);
if(c<0) continue;
char buff[1024]={0};
int n=recv(c,buff,1023,0);
if(n==0)
{
close(c);
continue;
}
printf("recv:%s\n",buff);
char*filename=get_filename(buff);
if(filename==NULL)
{
send(c,"404",3,0);
close(c);
continue;
}
char path[256]={PATH};
if(strcmp(filename,"/")==0)
{
stract(path,"index.tml");
}
else
{
stract(path,filename)
}
int fd=open(path,O_RDONLY);
if(fd==-1)
{
send(c,"404",3,0);
close(c);
continue;
}
int size=lseek(fd,0,SEEK_END);
lseek(fd,0,SEEK_SET);
char head[256]={0};
strcpy(hread,"HTTP/1.0 200 ok");
strcat(head,"Server: http");
sprintf(head+strlen(head),"Content-Length: %d",size);
strcat(head," ");
send(c,head,strlen(head),0);
printf("send head : %s",head);
char data[1024]={0};
int num=0;
while((num=read(fd,data,1024))>0)
{
send(c,data,num,0);
}
close(fd);
close(c);
}
}
char* get_filename(char buff[])
{
char* s=strtok(buff," ");
if(s==NULL)return NULL;
s=strtok(NULL," ");
return s;
}
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("127.0.0.1");
int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
if(res==-1)
{
return -1;
}
if(listen(sockfd,)==-1)
{
return -1;
}
return sockfd;
}
|