UDP是不保证数据传输的完整性,不基于连接,所以没有TCP的connect函数
TCP的发送和接收使用recvfrom和sendto函数,对端信息可以从这两个函数的最后两个函数的最后两个参数来获取或者设置。
1,基本的UDP c/s通信demo:
<span style="font-size:14px;">/*************************************************************
* file: udp_socket.c
* brief:udp demo program
* yejing@2015.3.25 1.0 creat
*************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <netinet/in.h>
#define PORT 9527
#if defined(SERVER)
int main(int argc, char* argv[]){
int sockfd;
struct sockaddr_in sockaddr_cli;
struct sockaddr_in sockaddr_svr;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(!sockfd){
fprintf(stderr, "socket create error. \n");
return -1;
}
sockaddr_svr.sin_family = AF_INET;
sockaddr_svr.sin_port = htons(PORT);
inet_pton(AF_INET, "127.0.0.1", &sockaddr_svr.sin_addr);
int ret = bind(sockfd, (const struct sockaddr*)&sockaddr_svr, sizeof(sockaddr_svr));
if(ret < 0){
fprintf(stderr, "socket bind error. errno:%d \n", errno);
return -1;
}
while(1){
char buf[10];
memset(buf, 0, sizeof(buf));
socklen_t sock_cli_len;
printf("read to recv \n");
ret = recvfrom(sockfd, buf, 10, 0, (struct sockaddr*)&sockaddr_cli, &sock_cli_len);
printf("ret = %d \n", ret);
#if 1
printf("rcving data:");
int i = 0;
for(i = 0; i < ret; ++i)
printf("%c ", buf[i]);
printf("\n");
#endif
if(ret){
ret = sendto(sockfd, buf, 10, 0, (const struct sockaddr*)&sockaddr_cli, sock_cli_len);
printf("ret = %d errno:%d \n", ret, errno);
}
}
}
#else
int main(int argc, char* argv[]){
int sockfd;
struct sockaddr_in sock_svr;
memset((char*)&sock_svr, 0, sizeof(sock_svr));
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(!sockfd){
fprintf(stderr, "socket create error, errno:%d \n", errno);
return -1;
}
sock_svr.sin_family = AF_INET;
sock_svr.sin_port = htons(PORT);
//inet_pton(AF_INET, argv[1], &sock_svr.sin_addr);
inet_pton(AF_INET, "127.0.0.1", &sock_svr.sin_addr);
while(1){
char sendbuf[10] = "asdfghjkl";
char rcvbuf[10] = {0};
int ret = sendto(sockfd, sendbuf, 10, 0, (const struct sockaddr*)&sock_svr, sizeof(sock_svr));
if(ret){
printf("sending data ... \n");
sleep(1);
printf("ret = %d 111\n", ret);
ret = recvfrom(sockfd, rcvbuf, 10, 0, NULL, NULL);
printf("ret = %d \n", ret);
if(ret){
printf("rcving echo:");
int i = 0;
for(i = 0; i < ret; ++i)
printf("%c ", rcvbuf[i]);
printf("\n");
}
}
}
}
#endif</span>
可靠性UDP编程:
如果想要让请求-应答式应用程序使用UDP,那么必须在客户程序中增加以下两个特性:
1,超时和重传,用于处理丢失的数据包
2,序列号,供客户验证一个应答是否匹配相应的请求。
并发UDP服务器:
与基于连接的TCP服务只是新创建一个task处理一个新的请求连接不同,UDP需要处理一下两种不同类型的服务器:
1,读入一个请求,发送一个应答,就不再跟这个客户交互
这种情形,读入客户请求的服务器可以通过创建一个task处理该请求。
2,服务器需要与客户多次交换数据
这个问题的关键在于服务器如何区分来至客户端的数据报属于哪个client,即归类client发来的数据包。方法通常是服务器为每个client创建一个新的socket,在上面绑定一个临时端口号,使用此端口号发送对client的应答,同时client需要记录server第一个应答的端口号,client的后续请求数据通过这个port发送给server。