我是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
函数,但我无法弄清楚原因?感谢。
答案 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 proxy
与Client
服务器建立连接,然后与目标服务器建立连接。
答案 1 :(得分:0)
这被设计破坏了!您必须决定哪个程序是服务器端(调用bind()
),哪个是客户端(调用connect()
)。这与读写无关,连接是双向的。但另一方面,一个体面的服务器应该能够accept()
多个连接...传统上这是通过分叉完成的,根据你的情况有更好的方法。
答案 2 :(得分:0)
有很多原因导致绑定失败。
首先,套接字已经连接,因此即使您没有指定它,它也已绑定到本地地址。当您调用connect时,系统会自动将套接字绑定到本地空闲地址。因此bind
调用应该失败。 bind
手册页给出了这个可能的错误
[EINVAL]套接字已绑定到某个地址,该协议不支持绑定到新地址...
并非全部。程序B已经在同一地址上侦听。因此,即使您关闭并重新打开套接字,绑定调用仍将失败:
[EADDRINUSE]指定的地址已被使用。
如果你不等待B关闭自己的套接字
这里的问题不在于C编程,而在于TCP / IP网络。域AF_INET中的套接字是由IP地址和端口号组成的2个端点之间的网络双向连接。一对(地址,端口)不能同时打开多次。因为此地址用于了解数据包的传递位置,因此必须是唯一的。
所以你应该:
最后但并非最不重要:
在向套接字写入后立即关闭套接字是错误和危险的:取决于网络配置,消息大小等,关闭可能会破坏可能尚未发送的部分最后一次写入。当你在loopback接口上使用短消息时,我不认为它发生在这里。但是,如果您想掌握套接字使用情况,可以试试graceful shutdown