求助:linux下socket编程(UDP)遇到的诡异现象……

cnctloveyu 2009-06-13 05:46:07
写TFTP服务器时遇到一个很奇怪的问题:
下面两条语句不能用,
struct sockaddr *p=&client_addr;
int ret=sendData(socket_fd,p,1,"hello",5);
但是如果替换为:int ret=sendData(socket_fd,&client_addr,1,"hello",5);
就可以正常执行,不知道为什么……
甚至,这样也不行:
struct sockaddr *p=&client_addr;//只是将&client_addr赋值给p,但是下面不用p也错……
int ret=sendData(socket_fd,&client_addr,1,"hello",5);
郁闷中……

完整的代码如下:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/times.h>
#include <sys/select.h>
#include <sys/socket.h>//for socket
#include <string.h>
#include <netinet/in.h>

const unsigned int BUF_SIZE =512;//TFTP max data length

int socket_init(char *ipString,unsigned short int port);
int sendData(int sock_fd,struct sockaddr *clientAddr,unsigned short block,char *data,int len);//send data to client

int main(int argc,char *argv[])
{

int socket_fd;
socket_fd=socket_init("127.0.0.1",69);//初始化网络,建立网络连接,返回socket_fd

char buf[BUF_SIZE];
int len_addr;
//struct sockaddr addr;
struct sockaddr client_addr;//store client address

bzero(&client_addr,sizeof(struct sockaddr));
int len=0;//store number of bytes recieved
len=recvfrom(socket_fd,buf,BUF_SIZE,0,&client_addr,&len_addr);


/****************************问题代码……********************/
//struct sockaddr *p=&client_addr;
int ret=sendData(socket_fd,&client_addr,1,"hello",5);
/****************************问题代码……********************/


printf("send %d bytes\n",ret);
}



int socket_init(char *ipString,unsigned short int port)
{
int sock_fd;//函数的返回值,建立的socket的文件描述符
int len;
unsigned long ip;//the ip to be binded
struct sockaddr_in tftp_addr;//address to be binded

len=sizeof(struct sockaddr_in);
bzero(&tftp_addr,len);//clear the value of tftp_addr


inet_pton(AF_INET,ipString,&ip);//字符串ip转为二进制ip存入ip变量

#ifdef TEST
fprintf(stdout,"debug:socket_init:ip=%d,port=%d\n",ip,port);
#endif

tftp_addr.sin_addr.s_addr=htonl(ip);//switch host format to network
tftp_addr.sin_family=AF_INET;//ipv4
tftp_addr.sin_port=htons(port);//switch host format to network
tftp_addr.sin_addr.s_addr=htonl(tftp_addr.sin_addr.s_addr); // ip


if( (sock_fd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) <0)
{
perror("socket_init:socket error");
exit(-1);
}

/* Enable address reuse */
int on = 1;
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );
if( (bind(sock_fd,(struct sockaddr *)&tftp_addr,len)) ==-1)
{
perror("socket_init:bind error");
exit(-1);
}

#ifdef TEST
fprintf(stdout,"debug:socket_init:udp init ok!\n");
#endif

return sock_fd; //返回网络描述符,实际代表一个网络连接

}


int sendData(int sock_fd,struct sockaddr *clientAddr,unsigned short block,char *data,int len)
{

char resOpcode[2];//respose data opcode
char resBlock[2];//data block number

//fill opcode
unsigned short opcode=htons(3);
memcpy(resOpcode,&opcode,2);

//fill block number
unsigned short num=htons(block);
memcpy(resBlock,&num,2);


//fill respose package
char *resPackage=(char *)malloc( sizeof(char) * (2+2+len) );
memcpy(resPackage,resOpcode,2);
memcpy(resPackage+2,resBlock,2);
memcpy(resPackage+4,data,len);

int ret=sendto(sock_fd,resPackage,len+4,0,clientAddr,sizeof(struct sockaddr) );//发送应答报文


fprintf(stdout,"debug:sendData:send %d byte.\n",ret);

return ret;

}







...全文
113 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
qizhao2001 2009-06-13
  • 打赏
  • 举报
回复
可能是 len=recvfrom(socket_fd,buf,BUF_SIZE,0,&client_addr,&len_addr); 这一句就没有收到UDP另一端的数据(len<=0),你没有判断, 这样 client_addr就不是个有效的地址了
cnctloveyu 2009-06-13
  • 打赏
  • 举报
回复
再次谢谢楼上几位!
goodname 2009-06-13
  • 打赏
  • 举报
回复
ssize_t recvfrom(int s, void *buf, size_t len, int flags,
struct sockaddr *from, socklen_t *fromlen);

fromlen,如果你传入有效指针,则应该用from的长度初始化一下。
cnctloveyu 2009-06-13
  • 打赏
  • 举报
回复
刚刚去man了一下recvfrom:
ssize_t recvfrom(int s, void *buf, size_t len, int flags,
struct sockaddr *from, socklen_t *fromlen);

The argument fromlen is a value-result
parameter, initialized to the size of the buffer associated with from, and modified on return to indicate the actual size of the address stored there.
看来确实要初始化……谢谢
cnctloveyu 2009-06-13
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 goodname 的回复:]

//struct sockaddr addr;
struct sockaddr client_addr;//store client address
int len_addr = sizeof(struct sockaddr);// <---------------这里初始化一下
bzero(&client_addr,sizeof(struct sockaddr));
int len=0;//store number of bytes recieved
len=recvfrom(socket_fd,buf,BUF_SIZE,0,&client_addr,&len_addr);
[/Quote]
试了一下,可以正常输出。
谢谢楼上!
顺便问一下,这个是什么原因……
goodname 2009-06-13
  • 打赏
  • 举报
回复

//struct sockaddr addr;
struct sockaddr client_addr;//store client address
int len_addr = sizeof(struct sockaddr);//<---------------这里初始化一下
bzero(&client_addr,sizeof(struct sockaddr));
int len=0;//store number of bytes recieved
len=recvfrom(socket_fd,buf,BUF_SIZE,0,&client_addr,&len_addr);
cnctloveyu 2009-06-13
  • 打赏
  • 举报
回复
perror的输出是:Invalid argument
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 cnctloveyu 的回复:]
我到sendData()函数里面看过了,指针的值是传过去了的……

sendData()函数里的:
int ret=sendto(sock_fd,resPackage,len+4,0,clientAddr,sizeof(struct sockaddr) );//发送应答报文
这一句返回-1.
[/Quote]

errno是什么呢?读出来看看
nadoo 2009-06-13
  • 打赏
  • 举报
回复
错误提示是什么?
cnctloveyu 2009-06-13
  • 打赏
  • 举报
回复
我到sendData()函数里面看过了,指针的值是传过去了的……

sendData()函数里的:
int ret=sendto(sock_fd,resPackage,len+4,0,clientAddr,sizeof(struct sockaddr) );//发送应答报文
这一句返回-1.
  • 打赏
  • 举报
回复
struct sockaddr *p=&client_addr;
int ret=sendData(socket_fd,p,1,"hello",5);
但是如果替换为:int ret=sendData(socket_fd,&client_addr,1,"hello",5);

这2句应该是完全没区别的,只是多了个指针副本而已,你说前面会出错,那你跟踪一下错误到了那里?形参传到了没?

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧