通过 C 中的套接字连接到服务器的多个连接
Multiple connections to server via socket in C
基本上我的程序应该能够同时与服务器建立多个连接。我有 运行,除非他们必须通过套接字发送大量文本,否则这是不可预测的。有时有效,有时无效。 plaintext4 文件长 69,333 字节,当我尝试通过套接字通过网络同时将它发送 5 次到服务器并返回时,它并不总是有效;有时它有效,有时它的一部分丢失,等等。当我使用基本上相同的东西使用写和读时它有效,但是当我尝试对大量文本进行相同时,它几乎根本不起作用,因此为什么我切换到发送和接收。现在我不知道如何做到这一点,所以当有人在某个时间发送时,没有其他人会同时发送……因为我认为这就是我遇到的问题。任何帮助都会很棒。
我的程序现在的状态:
- 发送少量文本时有效。
- 发送大量文本时不起作用。
- 它在不工作时创建的文件大小可能会有所不同,有时超过 60K 字节,有时甚至只有 20K 字节。这意味着在正确的进程接收到它之前,其他进程之一可能写入套接字或从中读取。 (我觉得)。
服务器代码
#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[])
{
const int BUFF_SIZE = 70000;
int sockfd, newsockfd, portno, newsockfdc;
socklen_t clilen;
char buffer[BUFF_SIZE];
pid_t pid;
int status;
char temp[BUFF_SIZE];
struct sockaddr_in serv_addr, cli_addr;
int n;
int i;
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 = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
while(1){
waitpid(-1, &status, WNOHANG);
memset(buffer, '[=10=]', sizeof(buffer));
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
if((pid=fork())==0)
{
close(sockfd);
int d;
for(i=0; i<1; i++)
{
bzero(buffer,BUFF_SIZE);
//sleep(1);
d=BUFF_SIZE-1;
//n = read(newsockfd,buffer,d);
n = recv(newsockfd, buffer, sizeof(buffer), 0);
if (n < 0) error("ERROR reading from socket");
bzero(temp, BUFF_SIZE);
strcpy(temp, buffer);
n = send(newsockfd, buffer, strlen(buffer)+1, 0);
//n = write(newsockfd,temp,sizeof(temp));
if (n < 0) error("ERROR writing to socket");
}
close(newsockfd);
exit(0);
}
else{
waitpid(-1, &status, WNOHANG);
close(newsockfd);
}
}
close(sockfd);
return 0;
}
客户代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
const int BUFF_SIZE = 70000;
char buffer[BUFF_SIZE];
if (argc < 4) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
int numt;
numt = atoi(argv[3]);
char numc[5];
bzero(numc, 5);
sprintf(numc, "%d", numt);
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
bzero(buffer,BUFF_SIZE);
FILE *fp;
size_t bytes_read;
if((fp=fopen("./plaintext4", "r+"))==NULL)
{
perror("fopen(2) file error");
exit(EXIT_FAILURE);
}
bytes_read = fread(buffer, sizeof(buffer), 1, fp);
fclose(fp);
sleep(1);
n=send(sockfd, buffer, strlen(buffer)+1, 0);
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,BUFF_SIZE);
n=BUFF_SIZE - 1;
n = recv(sockfd, buffer, sizeof(buffer), 0);
if (n < 0)
error("ERROR reading from socket");
char filei[90];
bzero(filei,90);
strcpy(filei, "plaintext");
strcat(filei, numc);
strcat(filei, "_a");
if((fp=fopen(filei, "w+"))==NULL)
{
perror("fopen(2) file error");
exit(EXIT_FAILURE);
}
bytes_read = fwrite(buffer, strlen(buffer), 1, fp);
fclose(fp);
close(sockfd);
return 0;
//sleep(1);
printf("Sending message 1: plaintext1\n");
bzero(buffer,BUFF_SIZE);
if((fp=fopen("./plaintext1", "r+"))==NULL)
{
perror("fopen(2) file error");
exit(EXIT_FAILURE);
}
bytes_read = fread(buffer, sizeof(buffer), 1, fp);
fclose(fp);
n = send(sockfd, buffer, strlen(buffer)+1, 0);
//n = write(sockfd, buffer, strlen(buffer));
if (n < 0)
error ("ERROR writing to socket client side");
bzero(buffer, BUFF_SIZE);
n=BUFF_SIZE - 1;
n = recv(sockfd, buffer, sizeof(buffer), 0);
//n = read(sockfd, buffer, n);
if (n < 0)
error("ERROR reading from socket client side");
printf("message: %s\n", buffer);
strcat(filei, "b");
if((fp=fopen(filei, "w+"))==NULL)
{
perror("fopen(2) file error");
exit(EXIT_FAILURE);
}
bytes_read = fwrite(buffer, strlen(buffer), 1, fp);
fclose(fp);
close(sockfd);
return 0;
}
您的服务器进程(调用 accept() 的进程)可能会被 waitpid 阻塞 - 这可能是您遇到问题的原因。
或者,您可以通过 SIGCHLD 信号处理程序实现 waitpid 调用,并从 main().
中删除 waitpid
此致!
基本上我的程序应该能够同时与服务器建立多个连接。我有 运行,除非他们必须通过套接字发送大量文本,否则这是不可预测的。有时有效,有时无效。 plaintext4 文件长 69,333 字节,当我尝试通过套接字通过网络同时将它发送 5 次到服务器并返回时,它并不总是有效;有时它有效,有时它的一部分丢失,等等。当我使用基本上相同的东西使用写和读时它有效,但是当我尝试对大量文本进行相同时,它几乎根本不起作用,因此为什么我切换到发送和接收。现在我不知道如何做到这一点,所以当有人在某个时间发送时,没有其他人会同时发送……因为我认为这就是我遇到的问题。任何帮助都会很棒。
我的程序现在的状态:
- 发送少量文本时有效。
- 发送大量文本时不起作用。
- 它在不工作时创建的文件大小可能会有所不同,有时超过 60K 字节,有时甚至只有 20K 字节。这意味着在正确的进程接收到它之前,其他进程之一可能写入套接字或从中读取。 (我觉得)。
服务器代码
#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[])
{
const int BUFF_SIZE = 70000;
int sockfd, newsockfd, portno, newsockfdc;
socklen_t clilen;
char buffer[BUFF_SIZE];
pid_t pid;
int status;
char temp[BUFF_SIZE];
struct sockaddr_in serv_addr, cli_addr;
int n;
int i;
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 = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
while(1){
waitpid(-1, &status, WNOHANG);
memset(buffer, '[=10=]', sizeof(buffer));
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
if((pid=fork())==0)
{
close(sockfd);
int d;
for(i=0; i<1; i++)
{
bzero(buffer,BUFF_SIZE);
//sleep(1);
d=BUFF_SIZE-1;
//n = read(newsockfd,buffer,d);
n = recv(newsockfd, buffer, sizeof(buffer), 0);
if (n < 0) error("ERROR reading from socket");
bzero(temp, BUFF_SIZE);
strcpy(temp, buffer);
n = send(newsockfd, buffer, strlen(buffer)+1, 0);
//n = write(newsockfd,temp,sizeof(temp));
if (n < 0) error("ERROR writing to socket");
}
close(newsockfd);
exit(0);
}
else{
waitpid(-1, &status, WNOHANG);
close(newsockfd);
}
}
close(sockfd);
return 0;
}
客户代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
const int BUFF_SIZE = 70000;
char buffer[BUFF_SIZE];
if (argc < 4) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
int numt;
numt = atoi(argv[3]);
char numc[5];
bzero(numc, 5);
sprintf(numc, "%d", numt);
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
bzero(buffer,BUFF_SIZE);
FILE *fp;
size_t bytes_read;
if((fp=fopen("./plaintext4", "r+"))==NULL)
{
perror("fopen(2) file error");
exit(EXIT_FAILURE);
}
bytes_read = fread(buffer, sizeof(buffer), 1, fp);
fclose(fp);
sleep(1);
n=send(sockfd, buffer, strlen(buffer)+1, 0);
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,BUFF_SIZE);
n=BUFF_SIZE - 1;
n = recv(sockfd, buffer, sizeof(buffer), 0);
if (n < 0)
error("ERROR reading from socket");
char filei[90];
bzero(filei,90);
strcpy(filei, "plaintext");
strcat(filei, numc);
strcat(filei, "_a");
if((fp=fopen(filei, "w+"))==NULL)
{
perror("fopen(2) file error");
exit(EXIT_FAILURE);
}
bytes_read = fwrite(buffer, strlen(buffer), 1, fp);
fclose(fp);
close(sockfd);
return 0;
//sleep(1);
printf("Sending message 1: plaintext1\n");
bzero(buffer,BUFF_SIZE);
if((fp=fopen("./plaintext1", "r+"))==NULL)
{
perror("fopen(2) file error");
exit(EXIT_FAILURE);
}
bytes_read = fread(buffer, sizeof(buffer), 1, fp);
fclose(fp);
n = send(sockfd, buffer, strlen(buffer)+1, 0);
//n = write(sockfd, buffer, strlen(buffer));
if (n < 0)
error ("ERROR writing to socket client side");
bzero(buffer, BUFF_SIZE);
n=BUFF_SIZE - 1;
n = recv(sockfd, buffer, sizeof(buffer), 0);
//n = read(sockfd, buffer, n);
if (n < 0)
error("ERROR reading from socket client side");
printf("message: %s\n", buffer);
strcat(filei, "b");
if((fp=fopen(filei, "w+"))==NULL)
{
perror("fopen(2) file error");
exit(EXIT_FAILURE);
}
bytes_read = fwrite(buffer, strlen(buffer), 1, fp);
fclose(fp);
close(sockfd);
return 0;
}
您的服务器进程(调用 accept() 的进程)可能会被 waitpid 阻塞 - 这可能是您遇到问题的原因。 或者,您可以通过 SIGCHLD 信号处理程序实现 waitpid 调用,并从 main().
中删除 waitpid此致!