C 中具有多个进程的 TCP Echo 服务器
TCP Echo Server with multiple processes in C
我正在尝试编写一个 TCP 回显服务器,它为每个连接创建一个新进程。但不知何故,它没有按预期工作。
#include <stdlib.h> // use common functions
#include <stdio.h> // use input/output functions
#include <string.h> // use string functions
#include <unistd.h> // use POSIX functions
#include <sys/socket.h> // use socket function
#include <netinet/in.h> // use internet address datatypes
#include <arpa/inet.h> // use inet_ntoa function
/** A simple server application in the internet domain using TCP.
The port number is passed as an argument to the program.
*/
#include <netdb.h>
#include <sys/wait.h>
void doprocessing (int sock);
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, clilen, status;
struct sockaddr_in serv_addr, cli_addr;
int pid;
// Read parameters
if (argc < 2) {
printf("Usage: TPCServer <port>\n");
return -1;
}
int port = atoi(argv[1]);
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
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(port);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *) &clilen)) {
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* Create child process */
pid = fork();
if (pid < 0) {
perror("ERROR on fork");
exit(1);
}
if (pid == 0) {
char buffer[256];
/* This is the client process */
close(sockfd);
while(recv(newsockfd, buffer, 100, 0)>0){
int n;
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("%s\n",buffer);
n = write(newsockfd,buffer,18);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
//newsockfd = accept(newsockfd, (struct sockaddr *) &cli_addr, (socklen_t *) &clilen);
}
exit(0);
}
else {
/* This is the parent process */
close(newsockfd);
waitpid(pid, &status, WNOHANG);
}
} /* end of while */
}
当我应该得到“foo42bar”时,我却得到了“bar����������������”。我认为问题在于保持连接。所以我希望这里有错误:
if (pid == 0) {
char buffer[256];
/* This is the client process */
close(sockfd);
while(recv(newsockfd, buffer, 100, 0)>0){
int n;
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("%s\n",buffer);
n = write(newsockfd,buffer,18);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
//newsockfd = accept(newsockfd, (struct sockaddr *) &cli_addr, (socklen_t *) &clilen);
}
exit(0);
}
感谢您的帮助。
您有两个问题:
在n = read(newsockfd,buffer,255);
之后,变量n
保存读取的字节数。那就是你应该打印的字节数和你应该写入的字节数。但是在您随后的打印和发送代码中,您没有使用 n
的值,因此您发送或打印的字符多于收到的字符,导致您看到垃圾。
由于您将缓冲区清零,因此您的打印可能会成功。尽管如果接收到的数据恰好包含零字节,那将会失败。但是对 write
的调用总是 发送 18 个字节,这可能太多或太少。
此外,出于某种原因,您在 while
循环中调用了 recv
并丢弃了结果。这将导致数据丢失。不要调用 recv
然后调用 read
。选择一个使用,不要丢弃结果,因为那是您要回显的数据。
我正在尝试编写一个 TCP 回显服务器,它为每个连接创建一个新进程。但不知何故,它没有按预期工作。
#include <stdlib.h> // use common functions
#include <stdio.h> // use input/output functions
#include <string.h> // use string functions
#include <unistd.h> // use POSIX functions
#include <sys/socket.h> // use socket function
#include <netinet/in.h> // use internet address datatypes
#include <arpa/inet.h> // use inet_ntoa function
/** A simple server application in the internet domain using TCP.
The port number is passed as an argument to the program.
*/
#include <netdb.h>
#include <sys/wait.h>
void doprocessing (int sock);
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, clilen, status;
struct sockaddr_in serv_addr, cli_addr;
int pid;
// Read parameters
if (argc < 2) {
printf("Usage: TPCServer <port>\n");
return -1;
}
int port = atoi(argv[1]);
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
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(port);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *) &clilen)) {
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* Create child process */
pid = fork();
if (pid < 0) {
perror("ERROR on fork");
exit(1);
}
if (pid == 0) {
char buffer[256];
/* This is the client process */
close(sockfd);
while(recv(newsockfd, buffer, 100, 0)>0){
int n;
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("%s\n",buffer);
n = write(newsockfd,buffer,18);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
//newsockfd = accept(newsockfd, (struct sockaddr *) &cli_addr, (socklen_t *) &clilen);
}
exit(0);
}
else {
/* This is the parent process */
close(newsockfd);
waitpid(pid, &status, WNOHANG);
}
} /* end of while */
}
当我应该得到“foo42bar”时,我却得到了“bar����������������”。我认为问题在于保持连接。所以我希望这里有错误:
if (pid == 0) {
char buffer[256];
/* This is the client process */
close(sockfd);
while(recv(newsockfd, buffer, 100, 0)>0){
int n;
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("%s\n",buffer);
n = write(newsockfd,buffer,18);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
//newsockfd = accept(newsockfd, (struct sockaddr *) &cli_addr, (socklen_t *) &clilen);
}
exit(0);
}
感谢您的帮助。
您有两个问题:
在n = read(newsockfd,buffer,255);
之后,变量n
保存读取的字节数。那就是你应该打印的字节数和你应该写入的字节数。但是在您随后的打印和发送代码中,您没有使用 n
的值,因此您发送或打印的字符多于收到的字符,导致您看到垃圾。
由于您将缓冲区清零,因此您的打印可能会成功。尽管如果接收到的数据恰好包含零字节,那将会失败。但是对 write
的调用总是 发送 18 个字节,这可能太多或太少。
此外,出于某种原因,您在 while
循环中调用了 recv
并丢弃了结果。这将导致数据丢失。不要调用 recv
然后调用 read
。选择一个使用,不要丢弃结果,因为那是您要回显的数据。