网络编程学习笔记(recvfrom很奇怪的一个地方)

recvfrom的最后一个参数不赋值时,返回的是一个很大的数。赋值后就是正常的

服务器端:

#include 
#include 
#include 
#include 
#include 
#include 

#define SERV_PORT 9999
#define BUF_LEN 128

void dg_echo(int sockfd, struct sockaddr_in *pcliaddr, socklen_t clilen)
{
	char buf[BUF_LEN];	
	socklen_t len;
	int n;

	for (;;) {
		len = clilen;
		if ((n = recvfrom(sockfd, buf, BUF_LEN, 0, (struct sockaddr*)pcliaddr, &len)) < 0) {
			printf("recvfrom error:%s\n", strerror(errno));
			continue;
		} 

		sendto(sockfd, buf, n, 0, (struct sockaddr*)pcliaddr, len);
		
	}	
}

int main(int argc, char **argv)
{
	struct sockaddr_in servaddr, clientaddr;
	int sockfd;

	sockfd = socket(AF_INET, SOCK_DGRAM, 0);	
	if (sockfd < 0) {
		printf("socket error:%s\n", strerror(errno));
		return -1;
	}

	memset(&servaddr, 0x00, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(SERV_PORT);
	
	if (bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
		printf("bind error:%s\n", strerror(errno));
		close(sockfd);	
		return -1;
	}
		
	dg_echo(sockfd, &clientaddr, sizeof(clientaddr));
	return 0;
}

客户端赋值时:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define SERV_PORT 9999
#define BUF_LEN 128

char *sock_ntop(const struct sockaddr* sockaddr, socklen_t len)
{
	static char str[BUF_LEN];
	char portstr[7];
	
	
	printf("sa_family1=%d, AF_INET=%d\n", sockaddr->sa_family, AF_INET);
	switch (sockaddr->sa_family) {
	case AF_INET:
		printf("enter...\n");		
		struct sockaddr_in *sin = (struct sockaddr_in*)sockaddr;
		if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == (const char *)NULL) {
			printf("inet_ntop error:%s\n", strerror(errno));
			return NULL;
		}	
		
	
		if (ntohs(sin->sin_port) != 0) {
			snprintf(portstr, sizeof(portstr), ":%d", ntohs(sin->sin_port));
			strcat(str, portstr);
		}
		return str;
	}	

	
	return NULL;	
}

void dg_cli(FILE *fp, int sockfd, const struct sockaddr_in * pservaddr, socklen_t servlen)
{
	int n;
	char sendline[BUF_LEN], recvline[BUF_LEN];
	struct sockaddr reply_addr;
	socklen_t len;

	while (fgets(sendline, BUF_LEN, fp) != NULL) {
		sendto(sockfd, sendline, strlen(sendline), 0, (struct sockaddr*)pservaddr, servlen);	
		//memset(&reply_addr, 0x00, sizeof(reply_addr));
		len = servlen;
		n = recvfrom(sockfd, recvline, BUF_LEN, 0, &reply_addr, &len);
		printf("sa_family=%d, servlen=%d, len=%d\n", reply_addr.sa_family, servlen, len);	
		if (len != servlen || memcmp(&reply_addr, pservaddr, len) != 0) {
			printf("receive (%s) ignored\n", sock_ntop(&reply_addr, len));
			continue;
		}
		
		recvline[n] = 0;
		fputs(recvline, stdout);
	}
}

int main(int argc, char **argv)
{
	struct sockaddr_in servaddr;
	int sock;

	memset(&servaddr, 0x00, sizeof(servaddr));	
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(SERV_PORT);	
	
	if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) < 0) {
		printf("inet_pton error:%s\n", strerror(errno));
		return -1;
	}

	sock = socket(AF_INET, SOCK_DGRAM, 0);	
	if (sock < 0) {
		printf("socket error:%s\n", strerror(errno));
		return -1;
	}

	dg_cli(stdin, sock, &servaddr, sizeof(servaddr));
	return 0;
}
输出为:


客户端没有赋值时,输出的乱码:



#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define SERV_PORT 9999
#define BUF_LEN 128

char *sock_ntop(const struct sockaddr* sockaddr, socklen_t len)
{
	static char str[BUF_LEN];
	char portstr[7];
	
	
	printf("sa_family1=%d, AF_INET=%d\n", sockaddr->sa_family, AF_INET);
	switch (sockaddr->sa_family) {
	case AF_INET:
		printf("enter...\n");		
		struct sockaddr_in *sin = (struct sockaddr_in*)sockaddr;
		if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == (const char *)NULL) {
			printf("inet_ntop error:%s\n", strerror(errno));
			return NULL;
		}	
		
	
		if (ntohs(sin->sin_port) != 0) {
			snprintf(portstr, sizeof(portstr), ":%d", ntohs(sin->sin_port));
			strcat(str, portstr);
		}
		return str;
	}	

	
	return NULL;	
}

void dg_cli(FILE *fp, int sockfd, const struct sockaddr_in * pservaddr, socklen_t servlen)
{
	int n;
	char sendline[BUF_LEN], recvline[BUF_LEN];
	struct sockaddr reply_addr;
	socklen_t len;

	while (fgets(sendline, BUF_LEN, fp) != NULL) {
		sendto(sockfd, sendline, strlen(sendline), 0, (struct sockaddr*)pservaddr, servlen);	
		//memset(&reply_addr, 0x00, sizeof(reply_addr));
		//len = servlen;
		n = recvfrom(sockfd, recvline, BUF_LEN, 0, &reply_addr, &len);
		printf("sa_family=%d, servlen=%d, len=%d\n", reply_addr.sa_family, servlen, len);	
		if (len != servlen || memcmp(&reply_addr, pservaddr, len) != 0) {
			printf("receive (%s) ignored\n", sock_ntop(&reply_addr, len));
			continue;
		}
		
		recvline[n] = 0;
		fputs(recvline, stdout);
	}
}

int main(int argc, char **argv)
{
	struct sockaddr_in servaddr;
	int sock;

	memset(&servaddr, 0x00, sizeof(servaddr));	
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(SERV_PORT);	
	
	if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) < 0) {
		printf("inet_pton error:%s\n", strerror(errno));
		return -1;
	}

	sock = socket(AF_INET, SOCK_DGRAM, 0);	
	if (sock < 0) {
		printf("socket error:%s\n", strerror(errno));
		return -1;
	}

	dg_cli(stdin, sock, &servaddr, sizeof(servaddr));
	return 0;
}

输出就不正确,接收的长度及sa_family都是不正确的

网络编程学习笔记(recvfrom很奇怪的一个地方)_第1张图片

哦,原来是这样的

recvfrom()
       recvfrom() places the received message into the buffer buf.  The
       caller must specify the size of the buffer in len.

       If src_addr is not NULL, and the underlying protocol provides the
       source address of the message, that source address is placed in the
       buffer pointed to by src_addr.  In this case, addrlen is a value-
       result argument.  Before the call, it should be initialized to the
       size of the buffer associated with src_addr.  Upon return, addrlen is
       updated to contain the actual size of the source address.  The
       returned address is truncated if the buffer provided is too small; in
       this case, addrlen will return a value greater than was supplied to
       the call.

       If the caller is not interested in the source address, src_addr and
       addrlen should be specified as NULL.

当中有这样一段话:

 Before the call, it should be initialized to the
       size of the buffer associated with src_addr.  Upon return, addrlen is
       updated to contain the actual size of the source address.


你可能感兴趣的:(网络编程,网络编程学习笔记)