您的位置:首页 > 编程语言

UDP中connet()的验证代码

2015-10-20 11:22 246 查看
Server:

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  udp