TCP与UDP的区别:
- 基于连接与无连接
- 对系统资源的要求(TCP较多,UDP较少)
- UDP程序结构简单
- 流模式与数据报模式
- TCP保证数据的正确性,UDP可能会丢包,TCP保证数据顺序,UDP不保证。
TCP与UDP的编程区别:
- socket()的参数不同
- UDP Server不需要调用listen和accept
- UDP收发数据用sendto/recvfrom函数
- TCP:地址信息在connect/accept时确定
- UDP:在sendto/recvfrom函数中每次均 需指定地址信息
UDP编程步骤:
- 创建一个socket,用函数socket()
- 绑定IP地址、端口等信息到socket上,用函数bind()
- 循环接收数据,用函数recvfrom()
- 关闭网络连接
一.创建套接字:函数socket()
1.所包含的头文件
#include <sys/types.h>
#include <sys/socket.h>
2.函数原型
int socket(int domain, int type, int protocol);
- domain:指定协议族,比如TCP/IP协议PF_INET PF_INET6
- type:指定服务器类型,SOCK_STREAM SOCK_UGRAM
- protocal:具体协议,通常默认为0
3.函数返回值:成功则返回socket文件描述符,失败则返回-1,设置errno
4.代码
int socketfd = socket(AF_INET,SOCK_DGRAM,0);
if(socketfd == -1)
{
perror("socket");
return -1;
}
二.绑定IP地址、端口等信息到socket上,用函数bind()
1.所包含的头文件
#include <sys/types.h>
#include <sys/socket.h>
2.函数原型
int bind(int sockfd, const struct sockaddr *my_addr,socklen_t addrlen);
- sockfd:socket文件描述符
- addr:指定socket绑定的地址
- addrlen:socket地址长度
3.函数返回值:成功则返回0,失败则返回-1,设置errno
4.代码
int ret;
int socketfd;
struct sockaddr_in server;
socketfd = socket(AF_INET,SOCK_DGRAM,0);
if(socketfd == -1)
{
perror("socket");
return -1;
}
ret = bind(socketfd,(struct sockaddr *)&server,sizeof(server));
if(ret == -1)
{
perror("bind");
return -1;
}
三. 循环接收数据,用函数recvfrom()
1.所包含的头文件
#include <sys/types.h>
#include <sys/socket.h>
2.函数原型
ssize_t recvfrom(int s, void *buf, size_t len, int flags,struct sockaddr *from, socklen_t *fromlen);
- sockfd:需要读写数据的sockfd
- buf :读写缓冲区的指针
- len :读写缓冲区的大小
- flags :通常设置为0
因为UDP没有连接的概念,因此每次读写数据都需要获取发送/接受端的socket地址,addrlen指定地址长度,flags参数同TCP
3.代码
while(1)
{
rev_len = recvfrom(socketfd,buf,sizeof(buf),0,(struct sockadd *)&client,&len);
if(rev_len < 0)
{
perror("recv");
return -1;
}
printf("buf = %s\n",buf);
memset(buf,0,100);
}
四:UDP服务器编程源代码
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <assert.h>
#include <unistd.h>
#define PORT 7891
#define BUF_LEN 100
int main(int argc,char ** argv)
{
int socketfd;
int rev_len;
int ret;
char buf[BUF_LEN] = {0};
int len = sizeof(struct sockaddr_in);
struct sockaddr_in server;
struct sockaddr_in client;
socketfd = socket(AF_INET,SOCK_DGRAM,0);
if(socketfd == -1)
{
perror("socket");
return -1;
}
bzero(&server,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = inet_addr(argv[1]);
ret = bind(socketfd,(struct sockaddr *)&server,sizeof(server));
if(ret == -1)
{
perror("bind");
return -1;
}
while(1)
{
rev_len = recvfrom(socketfd,buf,sizeof(buf),0,(struct sockaddr *)&client,&len);
if(rev_len < 0)
{
perror("recv");
return -1;
}
printf("buf = %s\n",buf);
memset(buf,0,100);
}
close(socketfd);
return 0;
}
五:UDP客户端编程
写数据用sendto()函数
1.所含头文件
#include <sys/types.h>
#include <sys/socket.h>
2.函数原型
ssize_t sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
参数参考recvfrom
3.udp客户端源代码
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <assert.h>
#define PORT 7891
#define MAX_LEN 100
int main(int argc,char ** argv)
{
int socketfd;
int send_len;
int len = sizeof(struct sockaddr_in);
char buf[MAX_LEN] = {0};
struct sockaddr_in server_addr;
socketfd = socket(AF_INET,SOCK_DGRAM,0);
if(socketfd < 0)
{
perror("socket");
return -1;
}
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr((const char *)argv[1]);
while(1)
{
printf("请输入文字\n");
scanf("%s",buf);
send_len = sendto(socketfd,buf,MAX_LEN,0,(struct sockaddr *)&server_addr,len);
}
close(socketfd);
return 0;
}