免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3640 | 回复: 9
打印 上一主题 下一主题

大家帮我看看这段服务器端代码哪里不对?为什么运行时bind出错? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-06-11 15:16 |只看该作者 |倒序浏览
代码如下:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>

#define MAXBUF 1024

int main(int argc, char *argv[])
{
int new_fd,sockfd = -1;
unsigned int port;
socklen_t len;
struct sockaddr_storage sas;
struct sockaddr_in* psin = (struct sockaddr_in*)(&sas);
struct sockaddr_in6* psin6 = (struct sockaddr_in6*)(&sas);
struct addrinfo aiHint;
struct addrinfo *aiList, *aiListCopy;
char buf[MAXBUF + 1];

port = 7838;
memset(&aiHint, 0, sizeof(aiHint));
aiHint.ai_socktype = SOCK_STREAM;
aiHint.ai_protocol = IPPROTO_TCP;
aiHint.ai_family = AF_UNSPEC;
if(!getaddrinfo(argv[1], "7838", &aiHint, &aiList))
{
// aiListCopy = aiList;
// do
for(aiListCopy=aiList; aiListCopy != NULL ;aiListCopy=aiListCopy->ai_next)  
  {
  if(aiListCopy->ai_family == AF_INET)
  {
  memcpy(&(psin->sin_addr), &(((struct sockaddr_in*)(aiListCopy->ai_addr))->sin_addr), sizeof(psin->sin_addr));
  psin->sin_port = htons(port);
  psin->sin_family = AF_INET;

  // socket
  if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {  
  perror("socket");
freeaddrinfo(aiListCopy);
  exit(1);
  } else
  printf("socket created\n");

//bind
  if (bind( sockfd, (struct sockaddr *)&psin, sizeof(struct sockaddr))){  
  perror("bind");
freeaddrinfo(aiListCopy);
  exit(1);
  } else
  printf("binded\n");

  //listen
  if (listen(sockfd, 1024) == -1) {
  perror("listen");
freeaddrinfo(aiListCopy);
  exit(1);
  } else
  printf("begin listen\n");

  }


  else if(aiListCopy->ai_family == AF_INET6)
  {
  memcpy(&(psin6->sin6_addr), &(((struct sockaddr_in6*)(aiListCopy->ai_addr))->sin6_addr), sizeof(psin6->sin6_addr));
  psin6->sin6_port = htons(port);
  psin6->sin6_family = AF_INET6;

  // socket
  if (( sockfd = socket(AF_INET6, SOCK_STREAM, 0)) == -1) {  
  perror("socket");
freeaddrinfo(aiListCopy);
  exit(1);
  } else
  printf("socket created\n");

//bind
  if (bind(sockfd, (struct sockaddr *) &psin6, sizeof(struct sockaddr_in6))){  
  perror("bind");
freeaddrinfo(aiListCopy);
  exit(1);
  } else
  printf("binded\n");

  //listen
  if (listen(sockfd, 1024) == -1) {
  perror("listen");
freeaddrinfo(aiListCopy);
  exit(1);
  } else
  printf("begin listen\n");

  }
   
  }//while(aiList = aiList->ai_next);

  freeaddrinfo(aiList);
}

  while (1) {
  len = sizeof(sas);
  if ((new_fd = accept(sockfd, (struct sockaddr *) &sas,&len)) == -1) {
  perror("accept");
  exit(errno);
  }  

  /* 开始处理每个新连接上的数据收发 */
  bzero(buf, MAXBUF + 1);
  strcpy(buf, "大家好\n");

  /* 发消息给客户端 */
  len = send(new_fd, buf, strlen(buf), 0);
  if (len < 0) {
  printf ("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buf, errno, strerror(errno));
  } else
  printf("消息'%s'发送成功,共发送了%d个字节!\n", buf, len);

  bzero(buf, MAXBUF + 1);
  /* 接收客户端的消息 */
  len = recv(new_fd, buf, MAXBUF, 0);
  if (len > 0)
  printf("接收消息成功:'%s',共%d个字节的数据\n",buf, len);
  else
printf ("消息接收失败!错误代码是%d,错误信息是'%s'\n",errno, strerror(errno));
  /* 处理每个新连接上的数据收发结束 */
  }

  close(sockfd);
return 0;
}

我想实现兼容IPV4,IPV6的服务器代码,在网上借鉴了不少代码,东改改西改改就有了以上代码,我看着好象没啥不对啊,
我的理解是,运行时,如果是输入的IPV4的IP地址,就创建IPV4的socket,IPV6的也一样,但是无论我运行那种都出现以下错误:
bind:cannot assign requested address.

大家帮我看看,我都快急死了,如果这种实现兼容IPV4,IPV6的服务器代码的方法不对,大家有更好的方法吗?
先谢过大家了.

论坛徽章:
0
2 [报告]
发表于 2010-06-11 15:45 |只看该作者
把getaddrinfo获取的ip地址打印出来看看,怀疑绑定的ip地址有误。。。

论坛徽章:
0
3 [报告]
发表于 2010-06-11 17:59 |只看该作者
本帖最后由 guaguaguaguaxi 于 2010-06-11 18:03 编辑

回复 2# rain_fish


    还真是地址有问题,这种方法好象不能用来做服务器端,只能作为客户端,如果我的getaddrinfo(argv[1], "7838", &aiHint, &aiList)的argv[1]为192.168.86.137,我之后
memcpy(&(psin->sin_addr), &(((struct sockaddr_in*)(aiListCopy->ai_addr))->sin_addr), sizeof(psin->sin_addr));出来的地址也是192.168.86.137,输入IPV6的地址也一样,就是我输入什么他输出什么,但是客户端的IP是未知的啊,我原本以为这里可以输入本机的IP,然后监听同网段的IP,看来是不行拉.
如果把argv[1]置为NULL,它的地址又为::,所以是不是作为服务器端是不对的,我这段代码也是借鉴网上的一段代码写的,人家是用做客户端的,如下:
os_socket_t os_net_open(const char* addr, unsigned short port)
{
int ret = -1;
struct sockaddr_storage sas;
struct sockaddr_in* psin = (struct sockaddr_in*)(&sas);
struct sockaddr_in6* psin6 = (struct sockaddr_in6*)(&sas);
struct addrinfo aiHint;
struct addrinfo *aiList, *aiListCopy;

// try ipv4
ret = inet_pton(AF_INET, addr, &(psin->sin_addr));
if(ret == 1)
{
  psin->sin_family = AF_INET;
  psin->sin_port = htons(port);
  // socket
  ret = socket(AF_INET, SOCK_STREAM, 0);
  if(ret == INVALID_SOCKET)
   return ret;
  // connect
  if(connect(ret, (const struct sockaddr*)psin, sizeof(sas)))
   return -1;
  else
   return ret;
}
// try ipv6
ret = inet_pton(AF_INET6, addr, &(psin6->sin6_addr));
if(ret == 1)
{
  psin6->sin6_family = AF_INET6;
  psin6->sin6_port = htons(port);
  // socket
  ret = socket(AF_INET6, SOCK_STREAM, 0);
  if(ret == INVALID_SOCKET)
   return ret;
  // connect
  if(connect(ret, (const struct sockaddr*)psin6, sizeof(sas)))
   return -1;
  else
   return ret;
}
// try hostname
memset(&aiHint, 0, sizeof(aiHint));
aiHint.ai_socktype = SOCK_STREAM;
aiHint.ai_protocol = IPPROTO_TCP;
aiHint.ai_family = AF_UNSPEC;
if(!getaddrinfo(addr, NULL, &aiHint, &aiList))
{
  aiListCopy = aiList;
  do
  {
   if(aiList->ai_family == AF_INET)
   {
    memcpy(&(psin->sin_addr), &(((struct sockaddr_in*)(aiList->ai_addr))->sin_addr), sizeof(psin->sin_addr));
    psin->sin_port = htons(port);
    psin->sin_family = AF_INET;
    // socket
    ret = socket(AF_INET, SOCK_STREAM, 0);
    if(ret == INVALID_SOCKET)
    {
     freeaddrinfo(aiListCopy);
     return -1;
    }
    // connect
    if(connect(ret, (const struct sockaddr*)psin, sizeof(sas)))
    {
     freeaddrinfo(aiListCopy);
     os_net_close(ret);
     return -1;
    }
    else
    {
     freeaddrinfo(aiListCopy);
     return ret;
    }
   }
   else if(aiList->ai_family == AF_INET6)
   {
    memcpy(&(psin6->sin6_addr), &(((struct sockaddr_in6*)(aiList->ai_addr))->sin6_addr), sizeof(psin6->sin6_addr));
    psin6->sin6_port = htons(port);
    psin6->sin6_family = AF_INET6;
    // socket
    ret = socket(AF_INET6, SOCK_STREAM, 0);
    if(ret == INVALID_SOCKET)
    {
     freeaddrinfo(aiListCopy);
     return -1;
    }
    // connect
    if(connect(ret, (const struct sockaddr*)psin6, sizeof(sas)))
    {
     os_net_close(ret);
     freeaddrinfo(aiListCopy);
     return -1;
    }
    else
    {
     freeaddrinfo(aiListCopy);
     return ret;
    }
   }
  }while(aiList = aiList->ai_next);
  freeaddrinfo(aiListCopy);
}

return -1;
}

所以用这种方法实现兼容IPV4和IPV6的服务器端是不行了吗?有其他方法没?

论坛徽章:
0
4 [报告]
发表于 2010-06-11 18:31 |只看该作者
难道你不能psin->sin_addr.s_addr=htonl(INADDR_ANY);然后再去bind?

论坛徽章:
0
5 [报告]
发表于 2010-06-12 09:53 |只看该作者
你可以加一句
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, len)试试

论坛徽章:
0
6 [报告]
发表于 2010-06-12 16:06 |只看该作者
回复 4# samlumengjun


    这个方法我试过了,结果还是一样,头大啊!!

论坛徽章:
0
7 [报告]
发表于 2010-06-12 16:08 |只看该作者
你可以加一句
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, len)试试
jimmyixy 发表于 2010-06-12 09:53


这个之前倒没有想到,应该是要加上去的,但是加上去之后还是一样的错,这下又懵了.

论坛徽章:
0
8 [报告]
发表于 2010-06-12 16:31 |只看该作者
回复 7# guaguaguaguaxi


  1.是检查一下端口是否被占用
  2. socket程序要规范一点,尤其初始化。例如你就没有 bzero(&psin, sizeof(psin));

论坛徽章:
0
9 [报告]
发表于 2010-06-12 16:35 |只看该作者
if(!getaddrinfo(argv[1], "7838", &aiHint, &aiList))
改为
if(!getaddrinfo(argv[1], "7838", &aiHint, aiList))

论坛徽章:
0
10 [报告]
发表于 2010-06-13 00:50 |只看该作者
加上这句psin->sin_addr.s_addr=htonl(INADDR_ANY);还不行的话感觉那就不是bind的错了吧~
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP