在TCP中,客户端调用connect函数会向服务器端触发一个TCP的3次握手过程,去建立一条TCP连接;而在UDP中,客户端调用该函数主要的作用是告诉后面将要调用的recvfrom函数,仅仅只接受在connect函数中指明的服务器发来的数据,这样当后面调用recvfrom时最后两个参数就可以置为NULL了。也就说对UDP编程来说,客户端调用connect是可选的:如果调用了connect函数,recvfrom就可以省掉最后两个参数;如果不调用connect则recvfrom必须指明从哪儿收数据。
/* server */ #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <netinet/ip.h> #define BUFSIZE 1024 int main(int argc, char *argv[]) { int sockfd = -1; int clientlen = 0; int ret; struct sockaddr_in serveraddr, clientaddr; char buf[BUFSIZE]; char sndbuf[BUFSIZE]; if (2 != argc || 0 > argv[1]){ printf("usage: %s:portnumber\n", argv[0]); exit(1); } if ( -1 == (sockfd = socket(AF_INET, SOCK_DGRAM, 0))){ perror("socket error:"); exit(1); } bzero(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_port = htons(atoi(argv[1])); serveraddr.sin_addr.s_addr = INADDR_ANY; //由于该值为0,所以转不转字节序都一样 if (-1 == (bind(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)))){ perror("bind error:"); exit(1); } clientlen = sizeof(clientaddr); while (1){ ret = recvfrom(sockfd, buf, sizeof(buf), 0, &clientaddr, &clientlen); if (ret < 0){ printf("recv data from %s:%d error\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port)); }else if (ret == 0){ perror("client has been closed socket"); }else{ printf("From %s:%d,%s\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port), buf); memset(sndbuf, 0, sizeof(sndbuf)); switch(buf[0]){ case 'a': strcpy(sndbuf, "After u, lady..."); break; case 'b': strcpy(sndbuf, "Before u, sir..."); break; case 'c': strcpy(sndbuf, "can u?"); break; default: strcpy(sndbuf, "I don't know what u want"); } puts(sndbuf); sendto(sockfd, sndbuf, strlen(sndbuf), 0, (struct sockaddr *)&clientaddr, sizeof(clientaddr)); } memset(buf, 0, sizeof(buf)); } return 0; }
/* client */ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/ip.h> #include <netinet/in.h> #include <netdb.h> int main(int argc, char *argv[]) { int portnumber = 0; int sockfd = -1; struct hostent *host; struct sockaddr_in serveraddr; char buf[1024] = {0}; char sndbuf[1024] = {0}; int len, ret; if (3 != argc || 0 > (portnumber = atoi(argv[2]))){ printf("usage:%s hostname portnumber\n", argv[0]); exit(1); } if (NULL == (host = gethostbyname(argv[1]))){ perror("gethostname error:"); exit(1); } if (-1 == (sockfd = socket(AF_INET, SOCK_DGRAM, 0))){ perror("socket error:"); exit(1); } bzero(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_port = htons(portnumber); serveraddr.sin_addr = *(struct in_addr *)host->h_addr; if (-1 == connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))){ perror("connect error:"); exit(1); } while (1){ memset(sndbuf, 0, sizeof(sndbuf)); len = read(0, sndbuf, sizeof(sndbuf)); ret = sendto(sockfd, sndbuf, strlen(sndbuf), 0, NULL, NULL); printf("len is %d, ret is %d\n", len, ret); if (ret == len){ memset(buf, 0, sizeof(buf)); ret = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL); if (ret < 0){ perror("read from server error"); }else if (ret == 0){ perror("server has been closed"); }else{ buf[ret] = 0; printf("from server:%s\n", buf); } } } return 0; }