C:在绑定之前使用write函数时出错

时间:2015-07-24 11:30:35

标签: c sockets serversocket

我是C的新手,并且套接字存在一些问题。我正在创建一个既是服务器又是客户端的程序(我不知道这是否可以接受,但是出于教育目的)。我希望程序做的是:当程序(A)运行时它应该向某人(程序B)发送一些字符串,然后成为服务器。在成为服务器时我的意思是它应该监听并接受传入的连接。这是我的程序代码A:

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

void error(const char *msg)
{
perror(msg);
exit(1);
}

int main(int argc, char *argv[])
{
 int sockfd, newsockfd, portno, number;
 socklen_t clilen;
 char buffer[256];
 struct sockaddr_in serv_addr, cli_addr;
 int n;
 if (argc < 2) {
     fprintf(stderr,"ERROR, no port provided\n");
     exit(1);
 }
 sockfd = socket(AF_INET, SOCK_STREAM, 0);
 if (sockfd < 0) 
    error("ERROR opening socket");
 bzero((char *) &serv_addr, sizeof(serv_addr));
 portno = atoi(argv[1]);



 serv_addr.sin_family = AF_INET;
 serv_addr.sin_addr.s_addr = 0;
 serv_addr.sin_port = htons(portno);


 connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr));
 number = write(sockfd,"Hey!",strlen("Hey!"));



 if (bind(sockfd, (struct sockaddr *) &serv_addr,
          sizeof(serv_addr)) < 0) 
          error("ERROR on binding");

 listen(sockfd,5);
 clilen = sizeof(cli_addr);
 sockfd = accept(sockfd, 
             (struct sockaddr *) &cli_addr, 
             &clilen);
 if (sockfd < 0) 
      error("ERROR on accept");
 bzero(buffer,256);
 n = read(sockfd,buffer,255);
 if (n < 0) error("ERROR reading from socket");
 printf("Here is the message: %s\n",buffer);
 n = write(sockfd,"I got your message",18);
 if (n < 0) error("ERROR writing to socket");
 close(sockfd);

 return 0; 
}

和程序B的代码:

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

void error(const char *msg)
{
perror(msg);
exit(1);
}

int main(int argc, char *argv[])
{
 int sockfd, newsockfd, portno;
 socklen_t clilen;
 char buffer[256];
 struct sockaddr_in serv_addr, cli_addr;
 int n;
 if (argc < 2) {
     fprintf(stderr,"ERROR, no port provided\n");
     exit(1);
 }
 sockfd = socket(AF_INET, SOCK_STREAM, 0);
 if (sockfd < 0) 
    error("ERROR opening socket");
 bzero((char *) &serv_addr, sizeof(serv_addr));
 portno = atoi(argv[1]);



 serv_addr.sin_family = AF_INET;
 serv_addr.sin_addr.s_addr = 0;
 serv_addr.sin_port = htons(portno);


 if (bind(sockfd, (struct sockaddr *) &serv_addr,
          sizeof(serv_addr)) < 0) 
          error("ERROR on binding");
 listen(sockfd,5);
 clilen = sizeof(cli_addr);
 sockfd = accept(sockfd, 
             (struct sockaddr *) &cli_addr, 
             &clilen);
 if (sockfd < 0) 
      error("ERROR on accept");
 bzero(buffer,256);
 n = read(sockfd,buffer,255);
 if (n < 0) error("ERROR reading from socket");
 printf("Here is the message: %s\n",buffer);
 n = write(sockfd,"I got your message",18);
 if (n < 0) error("ERROR writing to socket");
 close(sockfd);

 return 0; 
}

当我第一次运行程序B和A时,收到字符串,但程序A崩溃并在绑定时出现错误错误:无效的参数。此错误来自bind函数,但我无法弄清楚原因?感谢。

3 个答案:

答案 0 :(得分:0)

如果您希望代码同时作为ln -s /usr/lib/python3.4/site-packages/glib* /WHEREVER/IS/YOUR/VIRTUALENV/venv/lib/python3.4/site-packages/ Server,则会将其称为Client。我希望this link能帮助你实现这一目标。

TCP Proxy是充当客户端与另一台服务器之间的中介的服务器。 TCP proxyClient服务器建立连接,然后与目标服务器建立连接。

答案 1 :(得分:0)

这被设计破坏了!您必须决定哪个程序是服务器端(调用bind()),哪个是客户端(调用connect())。这与读写无关,连接是双向的。但另一方面,一个体面的服务器应该能够accept()多个连接...传统上这是通过分叉完成的,根据你的情况有更好的方法。

答案 2 :(得分:0)

有很多原因导致绑定失败。

首先,套接字已经连接,因此即使您没有指定它,它也已绑定到本地地址。当您调用connect时,系统会自动将套接字绑定到本地空闲地址。因此bind调用应该失败。 bind手册页给出了这个可能的错误

[EINVAL]套接字已绑定到某个地址,该协议不支持绑定到新地址...

并非全部。程序B已经在同一地址上侦听。因此,即使您关闭并重新打开套接字,绑定调用仍将失败:

[EADDRINUSE]指定的地址已被使用。

如果你不等待B关闭自己的套接字

这里的问题不在于C编程,而在于TCP / IP网络。域AF_INET中的套接字是由IP地址和端口号组成的2个端点之间的网络双向连接。一对(地址,端口)不能同时打开多次。因为此地址用于了解数据包的传递位置,因此必须是唯一的。

所以你应该:

  • 关闭并重新打开套接字
  • 等待一段时间(一秒钟应该足够了)让B在绑定到服务器地址之前关闭其套接字

最后但并非最不重要:

在向套接字写入后立即关闭套接字是错误和危险的:取决于网络配置,消息大小等,关闭可能会破坏可能尚未发送的部分最后一次写入。当你在loopback接口上使用短消息时,我不认为它发生在这里。但是,如果您想掌握套接字使用情况,可以试试graceful shutdown