发布时间:2015-11-06 16:48:24作者:知识屋
/**实践: 实现一个基于UDP的echo回声server/client**/ //server端代码 void echoServer(int sockfd); int main() { int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd == -1) err_exit("socket error"); struct sockaddr_in servAddr; servAddr.sin_family = AF_INET; servAddr.sin_addr.s_addr = htonl(INADDR_ANY); servAddr.sin_port = htons(8001); if (bind(sockfd, (const struct sockaddr *)&servAddr, sizeof(servAddr)) == -1) err_exit("bind error"); echoServer(sockfd); } void echoServer(int sockfd) { char buf[BUFSIZ]; ssize_t recvBytes = 0; struct sockaddr_in clientAddr; socklen_t addrLen; while (true) { memset(buf, 0, sizeof(buf)); addrLen = sizeof(clientAddr); memset(&clientAddr, 0, addrLen); recvBytes = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&clientAddr, &addrLen); //如果recvBytes=0, 并不代表对端连接关闭, 因为UDP是无连接的 if (recvBytes < 0) { if (errno == EINTR) continue; else err_exit("recvfrom error"); } cout << buf ; if (sendto(sockfd, buf, recvBytes, 0, (const struct sockaddr *)&clientAddr, addrLen) == -1) err_exit("sendto error"); } }
/**client端代码**/ void echoClient(int sockfd); int main() { int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd == -1) err_exit("socket error"); echoClient(sockfd); cout << "Client exiting..." << endl; } void echoClient(int sockfd) { struct sockaddr_in servAddr; servAddr.sin_family = AF_INET; servAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); servAddr.sin_port = htons(8001); char buf[BUFSIZ] = {0}; while (fgets(buf, sizeof(buf), stdin) != NULL) { if (sendto(sockfd, buf, strlen(buf), 0, (const struct sockaddr *)&servAddr, sizeof(servAddr)) == -1) err_exit("sendto error"); memset(buf, 0, sizeof(buf)); int recvBytes = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL); if (recvBytes == -1) { if (errno == EINTR) continue; else err_exit("recvfrom error"); } cout << buf ; memset(buf, 0, sizeof(buf)); } }UDP协议并不是像TCP一样是一对一的通信,UDP可以实现广播通信,并且由于是无连接的,只要知道对等方地址(ip和port) 都可以主动发数据。关闭server,再连接上,还可以进行通信。
总结:UDP客户或服务进程,仅在使用自己的UDP套接字与确定的唯一对端进行通信时,才会调用connect,当然,一般UDP客户端会用connect多一点。同时如果采用connect,其性能也会得到提升,因为对于sendto来讲,其发送数据前和后,需要连接套接字、断开套接字,如果connect之后,这两步就省下了。
7.UDP外出接口的确定:
假设客户端有多个IP地址,由connect /sendto 函数提供的远程地址的参数,系统会选择一个合适的出口,比如Server的IP是192.168.2.10, 而客户端现在的IP有 192.168.1.32 和 192.168.2.75 那么会自动选择192.168.2.75 这个IP出去。(具体算法先略过...)
最后附上数据报截断的一个示例:
int main() { int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd == -1) err_exit("socket error"); struct sockaddr_in servAddr; servAddr.sin_family = AF_INET; servAddr.sin_addr.s_addr = htonl(INADDR_ANY); servAddr.sin_port = htons(8001); if (bind(sockfd, (const struct sockaddr *)&servAddr, sizeof(servAddr)) == -1) err_exit("bind error"); //给自己发送数据 if (sendto(sockfd, "ABCDE", 5, 0, (const struct sockaddr *)&servAddr, sizeof(servAddr)) == -1) err_exit("sendto error"); for (int i = 0; i < 5; ++i) { char ch; int recvBytes = recvfrom(sockfd, &ch, 1, MSG_DONTWAIT, NULL, NULL); if (recvBytes == -1) { if (errno == EINTR) continue; else if (errno == EAGAIN) err_exit("recvfrom error"); } else cout << "char = " << ch << ", recvBytes = " << recvBytes << endl; } }
linux一键安装web环境全攻略 在linux系统中怎么一键安装web环境方法
Linux网络基本网络配置方法介绍 如何配置Linux系统的网络方法
Linux下DNS服务器搭建详解 Linux下搭建DNS服务器和配置文件
对Linux进行详细的性能监控的方法 Linux 系统性能监控命令详解
linux系统root密码忘了怎么办 linux忘记root密码后找回密码的方法
Linux基本命令有哪些 Linux系统常用操作命令有哪些
Linux必学的网络操作命令 linux网络操作相关命令汇总
linux系统从入侵到提权的详细过程 linux入侵提权服务器方法技巧
linux系统怎么用命令切换用户登录 Linux切换用户的命令是什么
在linux中添加普通新用户登录 如何在Linux中添加一个新的用户
2012-07-10
CentOS 6.3安装(详细图解教程)
Linux怎么查看网卡驱动?Linux下查看网卡的驱动程序
centos修改主机名命令
Ubuntu或UbuntuKyKin14.04Unity桌面风格与Gnome桌面风格的切换
FEDORA 17中设置TIGERVNC远程访问
StartOS 5.0相关介绍,新型的Linux系统!
解决vSphere Client登录linux版vCenter失败
LINUX最新提权 Exploits Linux Kernel <= 2.6.37
nginx在网站中的7层转发功能