在查看Beej的网络编程指南之后,我正在尝试使用select而不是fork来重做我的server.c.我不太确定会出现什么问题;我的程序编译,但不接受连接。我知道我的包含i< = fdmax的循环功能不正常,但我无法弄清楚原因。似乎if语句不能正常工作。
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>
#include <sys/select.h>
#define Connections 5
void SignalCatcher(int signum)
{
wait3(NULL,WNOHANG, NULL);
//wait(-1);
}
int main(int argc, char**argv)
{
int listenfd,connfd,n, i;
struct sockaddr_in servaddr,cliaddr;
socklen_t clilen;
pid_t childpid;
char mesg[1000];
FILE *inputFile;
inputFile = fopen("movie.txt", "r");
char returnMsg[1000];
int fdmax, newfd;
fd_set readfd;
fd_set mastersocket;
FD_ZERO(&mastersocket);
FD_ZERO(&readfd);
//Creating socket number
listenfd=socket(AF_INET,SOCK_STREAM,0);
//Setting up the internet address
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(32000);
bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
//Listening for clients
listen(listenfd,1024);
FD_SET(listenfd, &mastersocket);
fdmax=listenfd;
//signal(SIGCHLD, SIG_IGN);
signal(SIGCHLD, SignalCatcher);
//Infinite loop that waits for/accepts connections.
for(;;)
{
readfd = mastersocket;
clilen=sizeof(cliaddr);
if(select(fdmax+1, &readfd, NULL, NULL, NULL) == -1) {
perror("select");
exit(4);}
//connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
for(i=0; i<=fdmax;i++)
{
if (FD_ISSET(i, &readfd)){
if(i==listenfd){
printf("-SUCCESS\n");
clilen = sizeof cliaddr;
connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen); }
if (connfd!=-1)
{
// if ((childpid = fork()) == 0)
// {
close (listenfd);
for(;;)
{
n = recvfrom(connfd,mesg,1000,0,(struct sockaddr *)&cliaddr,&clilen);
if (n == -1 /*&& errno == EWOULDBLOCK*/) continue;
else if(n==0) break;
//sendto(connfd,mesg,n,0,(struct sockaddr *)&cliaddr,sizeof(cliaddr));
//write(connfd , mesg , strlen(mesg)); //both work
//write(connfd , "" , 1);
printf("-------------------------------------------------------\n");
printf("%d",listenfd);
mesg[n] = 0;
printf("Received the following:\n");
printf("%s",mesg);
printf("-------------------------------------------------------\n");
}
// }
close(connfd);
} //if connfd!=-1
}
} //for i<=fdmax
}
}
答案 0 :(得分:2)
您可以通过检查函数的返回值来自己回答这个问题。在网络编程中,通常的习惯用语是:
if (foo() < 0) {
fprintf(stderr, "foo: %s\n", strerror(errno));
/* recover from error or... */
exit(EXIT_FAILURE);
}
...其中foo()
是bind()
,listen()
,accept()
,send*/recv*()
之一,等等。
继续尝试。 errno
会告诉你什么是错的。
此外,目前还不清楚为什么要使用select()
。您所做的只是在一个插槽上侦听,并在有人连接后立即关闭它。相反,你可以accept(listenfd)
。
答案 1 :(得分:1)
首先你不应该在退出程序时关闭它应该关闭的监听fd。其次,我们需要接受在侦听套接字上排队的所有传入连接。然后,如果侦听套接字不可读,则现有连接必须是可读的,因此请读取该连接的数据。我只读过一次,但是你可以在循环中读取该连接,直到recv失败。
以下代码更改应该有效:
//Infinite loop that waits for/accepts connections.
for(;;)
{
readfd = mastersocket;
clilen=sizeof(cliaddr);
if(select(fdmax+1, &readfd, NULL, NULL, NULL) == -1) {
perror("select");
exit(4);}
//connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
for(i=0; i<=fdmax;i++)
{
if (FD_ISSET(i, &readfd)){
if(i==listenfd){
printf("-SUCCESS\n");
clilen = sizeof cliaddr;
connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
if (connfd!=-1)
{
FD_SET(connfd, &mastersocket);
if (connfd > fdmax) {
fdmax = connfd;
}
}
}
else
{
n = recvfrom(i,mesg,1000,0,(struct sockaddr *)&cliaddr,&clilen);
if ((n == -1 /*&& errno == EWOULDBLOCK*/) || (n==0)) {
close (i);
FD_CLR (i, &mastersocket);
if (i == fdmax)
{
while (FD_ISSET(fdmax, &mastersocket) == 0)
fdmax -= 1;
}
}
//sendto(i,mesg,n,0,(struct sockaddr *)&cliaddr,sizeof(cliaddr));
//write(i , mesg , strlen(mesg)); //both work
//write(i , "" , 1);
printf("-------------------------------------------------------\n");
printf("%d",listenfd);
mesg[n] = 0;
printf("Received the following:\n");
printf("%s",mesg);
printf("-------------------------------------------------------\n");
}
}
} //for i<=fdmax
}
答案 2 :(得分:0)
我尝试使用更改代码,对我来说工作正常。 此外,如果您希望一次只有一个客户端与服务器通信,则启用while循环以读取客户端数据。
server.c
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>
#include <sys/select.h>
#define Connections 5
void SignalCatcher(int signum)
{
wait3(NULL,WNOHANG, NULL);
//wait(-1);
}
int main(int argc, char**argv)
{
int listenfd,connfd,n, i;
struct sockaddr_in servaddr,cliaddr;
socklen_t clilen;
pid_t childpid;
char mesg[1000];
FILE *inputFile;
inputFile = fopen("movie.txt", "r");
char returnMsg[1000];
int fdmax, newfd;
fd_set readfd;
fd_set mastersocket;
FD_ZERO(&mastersocket);
FD_ZERO(&readfd);
//Creating socket number
listenfd=socket(AF_INET,SOCK_STREAM,0);
//Setting up the internet address
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(32000);
bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
//Listening for clients
listen(listenfd,1024);
FD_SET(listenfd, &mastersocket);
fdmax=listenfd;
//signal(SIGCHLD, SIG_IGN);
signal(SIGCHLD, SignalCatcher);
//Infinite loop that waits for accepts connections.
for(;;)
{
readfd = mastersocket;
clilen=sizeof(cliaddr);
if(select(fdmax+1, &readfd, NULL, NULL, NULL) == -1) {
perror("select");
exit(4);}
//connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
for(i=0; i<=fdmax;i++)
{
if (FD_ISSET(i, &readfd)){
if(i==listenfd){
printf("-SUCCESS\n");
clilen = sizeof cliaddr;
connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
if (connfd!=-1)
{
FD_SET(connfd, &mastersocket);
if (connfd > fdmax) {
fdmax = connfd;
}
}
}
else
{
//while(1) {
n = recvfrom(i,mesg,1000,0,(struct sockaddr *)&cliaddr,&clilen);
if ((n == -1 /*&& errno == EWOULDBLOCK*/) || (n==0)) {
close (i);
FD_CLR (i, &mastersocket);
if (i == fdmax)
{
while (FD_ISSET(fdmax, &mastersocket) == 0)
fdmax -= 1;
}
// break;
}
//sendto(i,mesg,n,0,(struct sockaddr *)&cliaddr,sizeof(cliaddr));
//write(i , mesg , strlen(mesg)); //both work
//write(i , "" , 1);
printf("-------------------------------------------------------\n");
printf("%d",listenfd);
mesg[n] = 0;
printf("Received the following:\n");
printf("%s",mesg);
printf("-------------------------------------------------------\n");
}
//} /* end of while */
}
} //for i<=fdmax
}
}
client.c
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define SERVER_PORT 32000
int main (int argc, char *argv[]) {
int sd, rc, i;
struct sockaddr_in localAddr, servAddr;
struct hostent *h;
char message[1000] ;
servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons( SERVER_PORT );
/* create socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
if(sd<0) {
perror("cannot open socket ");
exit(1);
}
/* bind any port number */
localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
localAddr.sin_port = htons(0);
rc = bind(sd, (struct sockaddr *) &localAddr, sizeof(localAddr));
if(rc<0) {
printf("%s: cannot bind port TCP %u\n",argv[0],SERVER_PORT);
perror("error ");
exit(1);
}
/* connect to server */
rc = connect(sd, (struct sockaddr *) &servAddr, sizeof(servAddr));
if(rc<0) {
perror("cannot connect ");
exit(1);
}
while(1)
{
printf("Enter message : ");
scanf("%s" , message);
rc = send(sd, message, strlen(message) + 1, 0);
if(rc<0) {
perror("cannot send data ");
close(sd);
exit(1);
}
printf("To_server: data%u sent (%s)\n",strlen(message),message);
}
return 0;
}