Относительно простого эхо-сервера на основе TCP с использованием Sockets API - PullRequest
2 голосов
/ 04 февраля 2012

Я изучаю сетевой интерфейс Sockets.В этом процессе я написал простой сервер Echo, который использует TCP.Я написал код таким образом, что, пока сервер работает, все, что было напечатано на консоли клиента, должно быть отражено в нем.Однако я не могу этого добиться.Хотя, для первого ввода, я получаю эхо, со следующего раза я не получаю никакого сообщения.Я знаю, что мы можем реализовать его для многих клиентов, используя fork(), но я хочу знать причину блокировки клиента и, если возможно, способы ее устранения.Вот код для клиента:

#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>

#define MAXCOUNT 1024

int main(int argc, char* argv[])
{
    int sfd;
    char msg[MAXCOUNT];
    char blanmsg[MAXCOUNT];
    struct sockaddr_in saddr;

    memset(&saddr,0,sizeof(saddr)); 
    sfd = socket(AF_INET,SOCK_STREAM,0);
    saddr.sin_family = AF_INET;
    inet_pton(AF_INET,"127.0.0.1",&saddr.sin_addr);
    saddr.sin_port = htons(5004);

    connect(sfd,(struct sockaddr*) &saddr, sizeof(saddr));
    for(; ;) {
        memset(msg,0,MAXCOUNT);
        memset(blanmsg,0,MAXCOUNT);
        fgets(msg,MAXCOUNT,stdin);
        send(sfd,msg,strlen(msg),0);
        recv(sfd,blanmsg,sizeof(blanmsg),0);
        printf("%s",blanmsg);
        fflush(stdout);
    }
    exit(0);
}   

Вот код для сервера:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>

#define MAXCOUNT 1024

int main(int argc, char* argv[])
{
    int sfd,nsfd,n,i,cn;
    char buf[MAXCOUNT];
    socklen_t caddrlen;
    struct sockaddr_in caddr,saddr; //Structs for Client and server Address in the Internet 

    sfd = socket(AF_INET,SOCK_STREAM,0);
    memset(&saddr,0,sizeof(saddr)); //Clear the Server address structure

    saddr.sin_family = AF_INET; //Internet Address Family
    saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    saddr.sin_port = htons(5004);

    bind(sfd, (struct sockaddr*) &saddr,sizeof(saddr));
    listen(sfd,1);

    for(; ;) {
        caddrlen = sizeof(caddr);
        nsfd = accept(sfd,(struct sockaddr*) &caddr,&caddrlen);
        cn = recv(nsfd,buf,sizeof(buf),0);
        if(cn == 0) {
            exit(0);
        }
        buf[cn] = '\0';
        send(nsfd,buf,strlen(buf),0);
        }
    close(nsfd);
    exit(0);
}       

Ответы [ 3 ]

6 голосов
/ 04 февраля 2012

Вы не должны вызывать accept в цикле на сервере. Переместите команду accept перед циклом for на сервере, и он должен работать так, как вы ожидаете.

Подобный вызов в цикле вызовет блокировку сервера до тех пор, пока не будет установлено новое соединение. Ваш клиент открывает только одно соединение, поэтому сервер заблокирует второй вызов для принятия.

1 голос
/ 04 февраля 2012

Ваш код делает именно то, что вы просили.Вы сказали ему принять соединение, получить некоторые данные из этого соединения, отправить эти данные обратно в соединение, а затем принять другое соединение.Это то, что он делает.Я подозреваю, что вы хотите переместить вызов accept за пределы цикла for.

0 голосов
/ 26 июля 2012
I think you required a code which servers multiple clients as well as echo message to respective clients.
so just have a look to your code again and note down modification

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#define MAXCOUNT 1024

int main(int argc, char* argv[])
{
int sfd,nsfd,n,i,cn;
char buf[MAXCOUNT];
socklen_t caddrlen;
struct sockaddr_in caddr,saddr; 
//Structs for Client and server Address in the Internet 

sfd = socket(AF_INET,SOCK_STREAM,0);
memset(&saddr,0,sizeof(saddr)); //Clear the Server address structure

saddr.sin_family = AF_INET; //Internet Address Family
saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
saddr.sin_port = htons(5004);

bind(sfd, (struct sockaddr*) &saddr,sizeof(saddr));
listen(sfd,5);/*request queue size*/
while(1)
{//main loop for cuncorent server
caddrlen = sizeof(caddr);
nsfd = accept(sfd,(struct sockaddr*) &caddr,&caddrlen);
if(fork()==0)
 {//only child code for serving a particular client
for(; ;) {//loop for reading and writing back msg cotineously


    cn = recv(nsfd,buf,sizeof(buf),0);
    if(cn == 0) {
        exit(0);
    }
    buf[cn] = '\0';
    send(nsfd,buf,strlen(buf),0);
    }//serving loop ends
close(nsfd);
exit(0);
   }//child code ends
  }//main while loop ends

exit(0);
}     
...