UDP中connet()的验证代码
2015-10-20 11:22
246 查看
Server:
Client:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main(int argc, char **argv) { int sockfd; struct sockaddr_in servaddr, fromAddr; socklen_t fromAddrLen; char *addrBuf; sockfd = socket(PF_INET, SOCK_DGRAM, 0); if(sockfd < 0){ perror("SOCKET :"); exit(1); } bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY);/* INADDR_ANY 指定IP地址为本地主机上任意IP地址 */ servaddr.sin_port = htons(8888); /* 端口为 8888 */ #if 1 /* 对于"服务器"来说,必须要要绑定一个客户端知道的端口号,客户端才能向该端口发送数据 */ if( bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){ perror("BIND :"); exit(1); } #endif int n; char recvline[1024]; memset(recvline, 0, sizeof(recvline)); printf("wait receiving....\n"); while(1){ memset(&fromAddr, 0, sizeof(fromAddr)); fromAddrLen = sizeof(fromAddr); /* 接收数据,所有到达本机的且端口号为8888的数据包都交由本进程处理 * 对方的地址会保存在fromAddr结构体中 */ if(recvfrom(sockfd, recvline, 1024, 0, (struct sockaddr *)&fromAddr, &fromAddrLen) < 0){ perror("Error :"); break; } addrBuf = inet_ntoa(fromAddr.sin_addr); printf("A client from %s:%d\n", addrBuf, ntohs(fromAddr.sin_port)); printf("%s\n", recvline); #if 1 strcpy(recvline, "ok"); if(sendto(sockfd, recvline, strlen(recvline), 0, (struct sockaddr *)&fromAddr, sizeof(fromAddr)) <= 0){ perror("Sendto : "); } #endif } printf("servce will exiting...\n"); close(sockfd); }
Client:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #include <errno.h> int main(int argc, char *argv[]) { int sock, recvLen; struct sockaddr_in toAddr, bindAddr, testAddr; struct sockaddr_in fromAddr; unsigned int fromLen; char recvBuffer[128]; char sendBuffer[] = "hello this is udp broadcast"; sock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); if(sock < 0){ fprintf(stderr,"socket():%s\n", strerror(errno)); exit(1); } memset(&toAddr,0,sizeof(toAddr)); toAddr.sin_family = AF_INET; toAddr.sin_addr.s_addr = inet_addr("192.168.1.20"); toAddr.sin_port = htons(8888); memset(&bindAddr, 0, sizeof(bindAddr)); bindAddr.sin_family = AF_INET; bindAddr.sin_addr.s_addr = htonl(INADDR_ANY); bindAddr.sin_port = htons(7777); memset(&testAddr, 0, sizeof(testAddr)); testAddr.sin_family = AF_INET; testAddr.sin_addr.s_addr = inet_addr("192.168.1.118"); testAddr.sin_port = htons(9999); int opt = 1; if(setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt)) != 0){ perror("setockopt() : \n"); close(sock); exit(1); } #if 1 /* 要"被动"的接收数据,必须绑定一个客户端知道的地址和端口,以便客户端主动向该地址发送数据 * 若进程不绑定地址和端口,则由内核自动为其选择一个合适的地址和端口,这样也能监听,但是客户端不 * 知道地址和端口,很不方便连接 */ if(bind(sock, (struct sockaddr *)&bindAddr, sizeof(bindAddr)) != 0){ perror("Bind : "); close(sock); exit(1); } #endif #if 1 /* 若想以后仅仅与一个主机通讯,则可以调用connect()指定目的地址,这样就可以调用recv(),send() * 这样发送的数据会到达toAddr, 进程也只能接收到toAddr发送的数据包 ,调用connect()之后,对于错误状态可知的情况, * 内核会返回到进程 */ if(connect(sock, (struct sockaddr *)&toAddr, sizeof(toAddr)) != 0){ perror("Connect : "); close(sock); exit(1); } #endif #if 0 /* 调用connect()之后,进程可以使用send()来代替sendto() */ if(send(sock, sendBuffer, strlen(sendBuffer), 0) <= 0){ perror("Send : "); close(sock); exit(1); }else{ printf("sent done!\n"); } #endif #if 1 /* 当然调用了connect()之后,进程仍然可以使用sendto(),但是第5、6个参数要么NULL,0,要么只能和原来的地址相同, * 否则会调用失败 */ if(sendto(sock, sendBuffer,strlen(sendBuffer),0,(struct sockaddr*)&toAddr,sizeof(toAddr)) != strlen(sendBuffer)){ fprintf(stderr,"sendto():%s\n", strerror(errno)); close(sock); exit(1); }else{ printf("sent done!\n"); } #endif #if 0 /* 调用connect()之后,进程仍然可以使用recvfrom(),但此时只能收到connect()指定的地址的发来的数据包 * 对于已知的错误,内核会告知进程,例如进程调用recvfrom()接收本机回环口127.0.0.1:8888的数据,若127.0.0.1:8888 * 有进程在监听,那么recvfrom()会阻塞,直到收到数据,若127.0.0.1并没有进程在监听,那么recvfrom()会直接返回,并且 * errno错误号会表明: "connection refused"。 * 若调用recvfrom接收网络上另一个地址发来的数据,即使该地址上并没有进程在工作,而内核也不知道 * 是否该主机上的某某端口是否打开,因为内核并不为UDP向该主机的端口发送任何探测报文(TCP三次握手完成,内核当然知道对方的状态), * 那么本机的进程也不会被告知错误 (可以写个程序验证)*/ fromLen = sizeof(fromAddr); memset(recvBuffer, 0, sizeof(recvBuffer)); if((recvLen = recvfrom(sock,recvBuffer,128,0,(struct sockaddr*)&fromAddr,&fromLen))<0){ fprintf(stderr,"recvfrom():%s\n", strerror(errno)); close(sock); exit(1); } printf("recvfrom() result len : %d, content %s\n", recvLen, recvBuffer); #endif #if 1 /* 调用了connect()之后,可以使用recv()来代替recvfrom() */ printf("receiving...\n"); if((recvLen = recv(sock, recvBuffer, 128, 0)) < 0){ perror("recv() : "); close(sock); exit(1); } printf("recv() result len : %d, content %s\n", recvLen, recvBuffer); #endif close(sock); return 0; }
相关文章推荐
- C#基于UDP实现的P2P语音聊天工具
- C#基于UDP进行异步通信的方法
- 距离详解Linux下的UDP方式通讯
- C#中使用UDP通信实例
- Linux网络编程之UDP Socket程序示例
- 服务器 UDP端口占用几千个的解决办法
- Android网络编程之UDP通信模型实例
- udp socket客户端和udp服务端程序示例分享
- PHP的Socket通信之UDP通信实例
- Android中实现TCP和UDP传输实例
- android开发socket编程之udp发送实例分析
- Linux网络编程之基于UDP实现可靠的文件传输示例
- python检测远程udp端口是否打开的方法
- python网络编程之数据传输UDP实例分析
- python基础教程之udp端口扫描
- python实现udp数据报传输的方法
- Python里disconnect UDP套接字的方法
- Java基于socket服务实现UDP协议的方法
- python网络编程之UDP通信实例(含服务器端、客户端、UDP广播例子)
- iptables下udp穿越实用篇----iptables与natcheck