初识协议
Posted ych9527
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初识协议相关的知识,希望对你有一定的参考价值。
1.协议
1.1结构化数据
程序员写的一个个解决实际问题,满足日常需求的网络程序都是在应用层
协议是一种约定、socket api的都是按照比特位的方式来进行发送和接收的,如果要传输一些"结构化的数据",怎么办呢?
结构化数据:比如发送QQ消息 、消息的组成有 -> 头像、称谓、信息、时间等等 ->这种数据就叫做结构化数据
1.2序列化和反序列化
序列化:发送信息的时候、需要将信息多变一
反序列化:接收信息、将信息一变多
序列化和反序列化工具(json、xml两种数据格式 -> 序列化和反序列化建议使用工具)
2.网络版的计算器
了解协议 -> 自定义协议实现网络计数器
//自定义协议
#pragma once
typedef struct Cal
{
int x;
int y;
char op;
int result;
int code;
}cal;
#pragma once
#include <iostream>
using namespace std;
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <unistd.h>
#include "protocol.hpp"
#include <netinet/in.h>
#include <arpa/inet.h>
#define NUM 5
class Server
{
private:
int port;
int lsock;
public:
Server(int _port)
:port(_port)
,lsock(-1)
{}
void InitServer()
{
//创建套接字
lsock=socket(AF_INET,SOCK_STREAM,0);
if(lsock < 0)
{
cerr<<"lsock error!!"<<endl;
exit(1);
}
//服务器绑定,填充服务器信息
struct sockaddr_in ser_add;
ser_add.sin_family=AF_INET;
ser_add.sin_port=htons(port);
ser_add.sin_addr.s_addr=INADDR_ANY;
if(bind(lsock,(struct sockaddr*)&ser_add,sizeof(ser_add))< 0)
{
cerr<<"bind error"<<endl;
exit(2);
}
//监听套接字
if(listen(lsock,NUM)< 0)
{
cerr<<"listen error"<<endl;
exit(3);
}
}
void Cal(int sock)
{
cal ret;
size_t size=recv(sock,&ret,sizeof(ret),0);
if(size>0)
{
ret.code=0;
switch(ret.op)
{
case'+':
ret.result=ret.x+ret.y;
break;
case '-':
ret.result=ret.x-ret.y;
break;
case'*':
ret.result=ret.x*ret.y;
break;
case '/':
if(ret.y==0)//除数不能为0
{
ret.code=1;
}
else
ret.result=ret.x/ret.y;
break;
default:
ret.code=2;//表示输入的操作数不符合
break;
}
}
send(sock,&ret,sizeof(ret),0);
close(sock);//短链接
}
void start()
{
sockaddr_in peer;//获取对方信息
socklen_t len =sizeof(peer);
//建立链接
while(true)
{
int sock=accept(lsock,(struct sockaddr*)&peer,&len);
if(sock < 0)
{
cerr<<"accept errot"<<endl;
continue;
}
if(fork()==0)//子进程
{
if(fork() > 0)//子进程退出
exit(0);
close(lsock);//孙子进程关闭监听套接字
Cal(sock);//调用任务函数
exit(0);//短链接、调用完就退出
}
close(sock);
waitpid(-1,nullptr,0);//等待任意子进程
}
}
~Server()
{
close(lsock);
}
};
#include "server.hpp"
void Usage(string str)
{
cout<<"Usage"<<"\\t"<<"\\n";
cout<<str<<":"<<"please enter your port"<<endl;
}
int main(int argc , char *argv[])
{
if(argc!=2)
{
Usage(argv[0]);
exit(5);
}
Server *sv=new Server(stoi(argv[1]));
sv->InitServer();
sv->start();
delete sv;
return 0;
}
#pragma once
#include <iostream>
using namespace std;
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <unistd.h>
#include "protocol.hpp"
#include <netinet/in.h>
#include <arpa/inet.h>
#define NUM 5
class Client
{
private:
string ip;
int port;
int sock;
public:
Client(string _ip,int _port)
:ip(_ip)
,port(_port)
,sock(-1)
{}
void InitClient()
{
//创建套接字
sock=socket(AF_INET,SOCK_STREAM,0);
if(sock < 0)
{
cerr<<"sock error!!"<<endl;
exit(1);
}
}
void start()
{
//发送给谁、填写信息
sockaddr_in ser_add;
ser_add.sin_family=AF_INET;
ser_add.sin_addr.s_addr=inet_addr(ip.c_str());//字符串转成网络整形
ser_add.sin_port=htons(port);
if(connect(sock,(struct sockaddr*)&ser_add,sizeof(ser_add))!=0)
{
cerr<<"connect error"<<endl;
exit(2);
}
//链接成功,发送信息
cal mes;
cout<<"please enter one num:";
cin>>mes.x;
cout<<"please enter two num:";
cin>>mes.y;
cout<<"please enter op:";
cin>>mes.op;
send(sock,&mes,sizeof(mes),0);
recv(sock,&mes,sizeof(mes),0);
cout<<"code:"<<mes.code<<" "<<"result:"<<mes.result<<endl;
}
~Client()
{
close(sock);
}
};
#include "client.hpp"
void Usage(string str)
{
cout<<"Usage"<<"\\t"<<"\\n";
cout<<str<<":"<<"please enter your ip and port"<<endl;
}
int main(int argc , char *argv[])
{
if(argc!=3)
{
Usage(argv[0]);
exit(5);
}
Client *ct = new Client(argv[1],atoi(argv[2]));
ct->InitClient();
ct->start();
delete ct;
return 0;
}
效果展示:
注意:
实验演示是在同一台机器上的,所以用相等的结构体相当于完成了数据的序列化和反序列化,但是这种方法是不推荐的。
因为不在同一台机器上时,用结构体来进行发送,内部对齐解释可能会不一样
3.抓包工具
tcpdump:传输层的协议基本可以抓
tcpdump -i 指定sniffer操作的侦听端口,比如:tcpdump -i eth0 , tcpdump -i lo0 。
tcpdump -i any 只要发送至这台主机的都要抓
-n:主机名这些能显示成数字就显示成数字
-nn:将更多的信息显示成数字
4.初识http协议
尽管应用层协议是由程序员自己来定的,但是已经有一些现成的并且非常好用的应用层协议,供我们直接参考使用,比如http(超文本传输协议)就是其中之一
4.1初识URL
URL就是平时俗称的网址
以上是关于初识协议的主要内容,如果未能解决你的问题,请参考以下文章
初识OpenGL 片段着色器(Fragment Shader)