【发布时间】:2019-05-11 19:20:54
【问题描述】:
我正在从这里http://www.linuxhowtos.org/C_C++/socket.htm 修改服务器代码。我想在客户端断开连接时重置服务器,以便下次为客户端准备好。但是当我关闭客户端时,服务器关闭并且服务器日志中没有任何内容。由于我一次只想处理一个客户,所以我不需要分叉,对吗?否则,服务器可以正常工作并响应我用 C# 编写的客户端发送的消息。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
FILE *fp;
double square(double x)
{
return x*x;
}
void error(const char *msg)
{
fprintf(fp, "%s", msg);
fprintf(fp, "%s", "\n");
}
int main(int argc, char *argv[])
{
fp = fopen("serverlog.txt", "a");
int sockfd;
int newsockfd;
int portno = 43635;
int clientIsConnected;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
while (1)
{
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
error("ERROR opening socket");
close(sockfd);
return 0;
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
error("ERROR on binding");
close(sockfd);
return 0;
}
if (listen(sockfd,5) < 0)
{
error("ERROR on listen");
close(sockfd);
return 0;
}
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
{
error("ERROR on accept");
close(newsockfd);
close(sockfd);
return 0;
}
clientIsConnected = 1;
while (clientIsConnected)
{
bzero(buffer, 256);
n = read(newsockfd, buffer, 255);
if (n < 0)
{
error("ERROR reading from socket");
clientIsConnected = 0;
break;
}
double x = atof(buffer);
double squared = square(x);
char response[256];
sprintf(response, "%f", squared);
n = write(newsockfd, response, strlen(response));
if (n < 0)
{
error("ERROR writing to socket");
clientIsConnected = 0;
break;
}
}
}
close(sockfd);
return 0;
}
【问题讨论】:
-
如果这不是一个玩具项目,我建议使用现有的库来处理网络层。您会发现这抽象出了很多与网络相关的问题,例如部分
write调用、意外断开连接等。