???
前言
TCP/UDP协议通俗易懂的介绍。
一、TCP协议/UDP协议
1.TCP协议:它是一种面向连接的传输层协议,它能够提供可靠的通信。TCP协议是在确定对方能够通信的前提下才传输数据,如果对方不能通信,那么我们可能会一直向对方发送通信请求,直到对方回应为止?,一旦回应,那么通信双方建立连接,开始传输数据。?
优点:TCP协议是数据无误、数据无丢失、数据无失序、数据无重复到达的通信协议。因此TCP协议一般是用于发送大量的数据。
2.UDP协议:它是不可靠的无连接的协议。在数据发送前,因为不需要进行连接,所以可以高效率的数据传输。UDP和TCP是不太一样的,UDP不会去确认目标是否能通信,它就只管往外?发送数据,至于对方能不能接收到,有没有数据丢失一概不管。?UDP一般用于发送少量的数据,因为量少,所以一般不会丢失。
优点:效率高。
二、代码现实
1.TCP协议
TCP协议代码如下(没添头文件):
//服务端
int Create_Socket(char *ip,char *port)
{
?? ?//1.创建套接字
?? ?int sock = socket(AF_INET,SOCK_STREAM,0);
?? ?if(sock == -1)
?? ?{
?? ??? ?perror("Create Socket Failed!");
?? ??? ?return -1;
?? ?}
?? ?//2.指定服务器(本机)的IP地址和端口号
?? ?struct sockaddr_in local;
?? ?local.sin_family = AF_INET;?? ??? ??? ??? ?//指定协议族
?? ?local.sin_port ?= htons(atoi(port));?? ?//指定网络程序的端口号
?? ?local.sin_addr.s_addr = inet_addr(ip);?? ?//指定IP地址
?? ?int ret = bind(sock,(struct sockaddr *)&local,sizeof(local));
?? ?if(ret == -1)
?? ?{
?? ??? ?perror("Bind Failed");
?? ??? ?close(sock);
?? ??? ?return -1;
?? ?}
?? ?//3.监听套接字
?? ?ret = listen(sock,10);
?? ?if(ret == -1)
?? ?{
?? ??? ?perror("Listen Failed");
?? ??? ?close(sock);
?? ??? ?return -1;
?? ?}
?? ?return sock;
}
/*
?? ?与confd对应的客户端进行通信
*/
void Handle_Tcp_Client(int confd,struct sockaddr_in client)
{
?? ?char buf[1024] = {0};
?? ?while(1)
?? ?{
?? ??? ?int ret = recv(confd,buf,sizeof(buf),0);
?? ??? ?if(ret > 0)
?? ??? ?{
?? ??? ??? ?buf[ret] = '\0';
?? ??? ??? ?printf("Recv From [ IP : %s ] [ PORT : %d ] : %s\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port),buf);
?? ??? ??? ?char *resp = "Thank You!I Recv Your Data!";
?? ??? ??? ?send(confd,resp,strlen(resp),0);
?? ??? ?}
?? ?}
}
int main(int argc,char **argv)
{
?? ?if(argc != 3)
?? ?{
?? ??? ?printf("Usage : %s <IP> <PROT>\n",argv[0]);
?? ??? ?return -1;
?? ?}
?? ?//将监听套接字准备好
?? ?int sock = Create_Socket(argv[1],argv[2]);
?? ?while(1)
?? ?{
?? ??? ?struct sockaddr_in client;
?? ??? ?//每当有一个客户端申请与服务器进行连接时,开辟一个进程去处理
?? ??? ?//当前客户端与服务器的通信,而主线程继续监听
?? ??? ?socklen_t len = ?sizeof(client);
?? ??? ?int confd = accept(sock,(struct sockaddr *)&client,&len);
?? ??? ?if(confd == -1)
?? ??? ?{
?? ??? ??? ?perror("Accept Failed");
?? ??? ??? ?return -1;
?? ??? ?}
?? ??? ?printf("Connect [ IP : %s ] [ PORT : %d ]\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
?? ??? ?//创建一个子进程去与当前客户端进行通信
?? ??? ?pid_t pid = fork();
?? ??? ?if(pid == -1)
?? ??? ?{
?? ??? ??? ?perror("Fork Failed");
?? ??? ??? ?return -1;
?? ??? ?}
?? ??? ?else if(pid == 0)
?? ??? ?{
?? ??? ??? ?//子进程负责与客户端进行通信
?? ??? ??? ?Handle_Tcp_Client(confd,client);
?? ??? ?}
?? ??? ?else?
?? ??? ?{
?? ??? ??? ?close(confd);//关闭连接套接字
?? ??? ?}
?? ?}
}
//客服端
/*
根据IP地址字符串和端口号字符串创建套接字
@返回值:成功返回套接字,失败返回-1
*/
int Create_Socket(char *ip,char *port)
{
//创建套接字
int sock = socket(AF_INET,SOCK_STREAM,0);
if(sock == -1)
{
perror("Create Socket Failed!");
return -1;
}
return sock;
}
/*
./tcp_client <ser_ip> <ser_port>
*/
int main(int argc,char **argv)
{
if(argc != 3)
{
printf("Usage : %s <IP> <PROT>\n",argv[0]);
return -1;
}
//将套接字准备好
int sock = Create_Socket(argv[1],argv[2]);
//根据服务器IP和服务器的PORT与指定的服务器进行连接
struct sockaddr_in server;
server.sin_family = AF_INET; //指定协议族
server.sin_port = htons(atoi(argv[2])); //指定网络程序的端口号
server.sin_addr.s_addr = inet_addr(argv[1]); //指定IP地址
int ret = connect(sock,(struct sockaddr *)&server,sizeof(server));
if(ret == -1)
{
perror("Connect Server Failed");
return -1;
}
char buf[256];
while(1)
{
//通过套接字往服务器上发送数据
scanf("%s",buf);
send(sock,buf,strlen(buf),0);
//接收服务器回给我们的数据
recv(sock,buf,sizeof(buf),0);
printf("服务器回应:%s\n",buf);
}
}
2.UDP
udp协议代码如下(没添头文件):
/*
UDP服务端
./udp_server ip port
*/
/*
根据IP地址字符串和端口号字符串创建套接字
@返回值:成功返回套接字,失败返回-1
*/
int Create_Udp_Socket(char *ip,char *port)
{
//1.创建套接字
int sock = socket(AF_INET,SOCK_DGRAM,0);
if(sock == -1)
{
perror("Create Socket Failed!");
return -1;
}
//2.指定服务器(本机)的IP地址和端口号
struct sockaddr_in local;
local.sin_family = AF_INET; //指定协议族
local.sin_port = htons(atoi(port)); //指定网络程序的端口号
local.sin_addr.s_addr = inet_addr(ip); //指定IP地址
int ret = bind(sock,(struct sockaddr *)&local,sizeof(local));
if(ret == -1)
{
perror("Bind Failed");
close(sock);
return -1;
}
return sock;
}
int main(int argc,char **argv)
{
if(argc != 3)
{
printf("Usage : %s <IP> <PROT>\n",argv[0]);
return -1;
}
//将套接字准备好
int sock = Create_Udp_Socket(argv[1],argv[2]);
while(1)
{
char buf[1024] = {0};
struct sockaddr_in udp_client;
socklen_t len = sizeof(udp_client);
//接收客户端发送的数据
int ret = recvfrom(sock,buf,sizeof(buf) - 1,0,(struct sockaddr *)&udp_client,&len);
if(ret > 0)
{
printf("Recv Data [ %s ] From [ %s : %d ]\n",buf,inet_ntoa(udp_client.sin_addr),ntohs(udp_client.sin_port));
sendto(sock,"OK",2,0,(struct sockaddr *)&udp_client,len);
}
sleep(2);
}
close(sock);
}
/*
UDP客户端
./udp_client ser_ip ser_port
*/
/*
根据IP地址字符串和端口号字符串创建套接字
@返回值:成功返回套接字,失败返回-1
*/
int Create_Udp_Socket()
{
//1.创建套接字
int sock = socket(AF_INET,SOCK_DGRAM,0);
if(sock == -1)
{
perror("Create Socket Failed!");
return -1;
}
/*
//2.指定客户端(本机)的IP地址和端口号
struct sockaddr_in local;
local.sin_family = AF_INET; //指定协议族
local.sin_port = htons(atoi(port)); //指定网络程序的端口号
local.sin_addr.s_addr = inet_addr(ip); //指定IP地址
int ret = bind(sock,(struct sockaddr *)&local,sizeof(local));
if(ret == -1)
{
perror("Bind Failed");
close(sock);
return -1;
}
*/
return sock;
}
int main(int argc,char **argv)
{
if(argc != 3)
{
printf("Usage : %s <IP> <PROT>\n",argv[0]);
return -1;
}
//将套接字准备好
int sock = Create_Udp_Socket();
if(sock == -1)
{
}
while(1)
{
char buf[1024] = {"Hello,Udp Server!"};
struct sockaddr_in udp_server;
socklen_t len = sizeof(udp_server);
udp_server.sin_family = AF_INET;
udp_server.sin_port = htons(atoi(argv[2])); //指定网络程序的端口号
udp_server.sin_addr.s_addr = inet_addr(argv[1]);//指定IP地址
int ret = sendto(sock,buf,strlen(buf),0,(struct sockaddr *)&udp_server,len);
if(ret == -1)
{
perror("Send Failed");
return -1;
}
ret = recvfrom(sock,buf,sizeof(buf),0,NULL,NULL);
buf[ret] = '\0';
printf("%s\n",buf);
}
close(sock);
}
总结
这两种协议各有各的好处,TCP更可靠稳定,而UDP虽然没有那么可靠但是效率高。所以现在应用的更多的反而是UDP。
|