您的位置:首页 > 理论基础 > 计算机网络

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

2014-09-28 22:02 246 查看
recvfrom的最后一个参数不赋值时,返回的是一个很大的数。赋值后就是正常的

服务器端:

#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

#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 <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#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
= 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 <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>

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