linux下获取sendto的错误码,套接字sendto()失败了errno 88和9

我正在尝试使用UDP(作为练习)运行一个简单的客户端 - 服务器应用程序,OS Linux Mint 14.客户端在启动时向服务器发送请求以获取一些会话参数,包括usec中的超时 . 客户端打开一个套接字并设置一个默认超时值,以便在recvfrom上不被无限制地阻塞,然后发送对这些参数的请求,关闭所述套接字,重新打开设置新超时值的套接字,最后询问用户用于命令 .

参数请求由子函数处理,该子函数除了其他之外还获得指向客户端套接字的指针,因此如果新的sockfd是不同的数字,则主函数也将能够引用新的套接字 . (返回值用作检查值,零或非零)

顺序是:

客户端调用子函数传递套接字指针

子功能发送请求

子功能得到答案

子功能关闭旧套接字

子函数在套接字指针指向的位置打开新的套接字(socket(),setsockopt,bind())(从而替换原文)

- 问题

下一次调用sendto()失败的情况是errno 9(文件编号错误)或errno 88(非套接字上的套接字操作) .

在main中调用函数:(servaddr是一个struct sockaddr_in,因此是强制转换; sockfd是一个int)

int checkParameters;

checkParameters=clientrequest(&sockfd, (struct sockaddr*) &servaddr, 0, settings);

clientrequest()描述:

int clientparameters(int* socketpt, struct sockaddr* remaddr, unsigned int parameters[])

{

unsigned char timeouts = 0;

int received = 0;

socklen_t len;

unsigned char* buff;

if((buff = malloc(MAX_LINE)) == NULL) {

fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);

return -1;

}

unsigned char i;

memset(buff, 0, MAX_LINE);

if(encode(buff, PARAM) < 0) {

fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);

free(buff);

return -1;

}

if(sendto(*socketpt, buff, 1, 0, remaddr, sizeof(struct sockaddr)) < 0) {

fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);

free(buff);

return -1;

}

while(received == 0) {

len = sizeof(struct sockaddr);

if((received = recvfrom(*socketpt, buff, MAX_LINE, 0, remaddr, &len)) < 0) {

if(errno == EWOULDBLOCK) {

if(timeouts == TIMEOUT_NUM) {

fprintf(stderr, "Server non found, process %d, errno %d\n", getpid(), errno);

free(buff);

return -1;

}

received = 0;

timeouts++;

}

else {

fprintf(stderr, "Error occurred, process %d\n errno: %d\n", getpid(), errno);

free(buff);

return -1;

}

}

}

}

memcpy(parameters, uncap(buff), sizeof(unsigned int)*3);

/*"uncap" removes user-level protocol header from payload*/

free(buff);

/*Store old socket port + IP address*/

struct sockaddr_in addr;

len = sizeof(struct sockaddr);

if(getsockname(*socketpt, (struct sockaddr*)&addr, &len) < 0) {

fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);

return -1;

}

if(close(*socketpt) < 0) {

fprintf(stderr,"Errore occurred, process %d, errno %d\n", getpid(), errno);

return -1;

}

/*Opens new socket*/

if(((*socketpt) = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {

fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);

return -1;

}

/*Set timer*/

struct timeval t;

t.tv_usec = parameters[2]; //Where timer is set

if(setsockopt(*socketpt, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval)) < 0 ) {

fprintf(stderr, "errno: %d\n win: %u\t loss: %u\t timeout: %u\n\n", errno, parameters[0], parameters[1], parameters[2]);

fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);

if(close(*socketpt) < 0) {

fprintf(stderr, "Errore in close() in clientrequest(), processo %d, errno %d\n", getpid(), errno);

}

return(-1);

}

if(bind(*socketpt, (struct sockaddr*)&addr, sizeof(struct sockaddr)) < 0) {

fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);

if(close(*socketpt) < 0) {

fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);

}

return(-1);

}

return 0;

}

一旦我输入第二个请求函数,它在第一个sendto()失败,错误为88 .

这是我尝试过的一些沙盒代码 . 它基本上遵循相同的socket(),setsockopt(),bind(),sendto(),close()方法,除了“sendto”发送到套接字绑定的相同IP /端口 .

int* receptionfd = malloc(4);

struct sockaddr_in addr;

char buff[MAX_LINE];

int n;

unsigned int len;

if((*receptionfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {

perror("Error occurred\n");

free(receptionfd);

exit(-1);

}

memset((void*)&addr, 0, sizeof(addr));

addr.sin_family = AF_INET;

if(inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) <= 0) {

perror("Errore occurred\n");

free(receptionfd);

exit(-1);

}

addr.sin_port = htons(5050);

struct timeval t;

t.tv_usec = 20000;

if(setsockopt(*receptionfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval)) < 0 ) {

fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);

if(close(*receptionfd) < 0) {

fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);

}

return(-1);

}

if(bind(*receptionfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {

perror("Error occurred\n");

free(receptionfd);

exit(-1);

}

if(sendto(*receptionfd, buff, 0, 0, (struct sockaddr*)&addr, sizeof(struct sockaddr)) < 0) {

fprintf(stderr, "Error occurred, first sendto(), errno %d\n", errno);

free(receptionfd);

exit(-1);

}

else

printf("First good\n");

close(*receptionfd);

createsock(receptionfd, addr);

if(sendto(*receptionfd, buff, 0, 0, (struct sockaddr*)&addr, sizeof(struct sockaddr)) < 0) {

fprintf(stderr, "Error occurred, second sendto(), errno %d\n", errno);

free(receptionfd);

exit(-1);

}

else {

printf("Second good\n");

}

close(*receptionfd);

free(receptionfd);

exit(0);

createsock()体:

void createsock(int* receptionfd, struct sockaddr_in addr) {

if(((*receptionfd) = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {

perror("Error occurred\n");

free(receptionfd);

exit(-1);

}

memset((void*)&addr, 0, sizeof(addr));

addr.sin_family = AF_INET;

if(inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) <= 0) {

perror("Error occurred\n");

free(receptionfd);

exit(-1);

}

addr.sin_port = htons(5050);

struct timeval t;

t.tv_usec = 20000;

if(setsockopt(*receptionfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval)) < 0 ) {

fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);

if(close(*receptionfd) < 0) {

fprintf(stderr, "Error occurred, process %d, errno %d\n", getpid(), errno);

}

}

if(bind(*receptionfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {

perror("Error occurred\n");

exit(-1);

}

}

(您可能会注意到我从主沙箱功能中复制了一些东西)好吧,沙箱总是执行“First good,Second good” . 我可能会使用“select()”来解决它是否有效,但我宁愿理解为什么会这样做 .

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值