套接字编程-简单的客户端/服务器

时间:2020-02-09 06:24:35

标签: c linux sockets server client

我应该在Linux上使用客户端在与服务器连接的套接字上编写C程序,提供登录凭据,服务器根据文件验证这些凭据,然后根据有效/无效状态返回不同的消息

到目前为止,我的服务器代码是:

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

void error(char *msg)
{
    perror(msg);
    exit(1);
}

void sendResponse(int newsockfd, int n)
{
    n = write(newsockfd, "Welcome to CPSC445-Comp Networking class\nYou are invited to use Fortnight", 73);
    if (n < 0)
    {
        error("ERROR writing to socket");
    }
}

void sendResponse1(int newsockfd, int n)
{
    n = write(newsockfd, "Only for ESU CPSC students taking CPSC445\nYou are not yet invited", 66);
    if (n < 0)
    {
        error("ERROR writing to socket");
    }
}

int readPass(int newsockfd, int n, char buffer[], int i)
{
    int u = i;
    bzero(buffer, 256);
    n = read(newsockfd,buffer,255);
    if (n < 0)
    {
        error("ERROR reading from socket");

    }


    char newbuf[256];
    char user[8];
    char pass[8];
    FILE *f1;

    f1 = fopen("passwd.txt", "r");

    for (int i = 0; i<=u; i++)
    {   
        fgets(newbuf, 256, f1);
        sscanf(newbuf, "%[^:]_%[^:]", user, pass);;
    }
    if (strcmp(buffer, pass) == 0)
    {
        n = write(newsockfd, "1", 1);
        sendResponse(newsockfd, n);
        return 1;
    }
    else
    {
        n = write(newsockfd, "Invalid password, please try again\n", 33);
        return 0;
    }
    sendResponse1(newsockfd, n);
    return 0;
}

int readUser(int newsockfd, int n, char buffer[])
{
    bzero(buffer, 256);
    n = read(newsockfd,buffer,255);
    printf("%s", buffer);

    if (n < 0)
    {
        error("ERROR reading from socket");

    }

    char valid[1];  
    char newbuf[256];
    char user[8];
    FILE *f1;

    f1 = fopen("passwd.txt", "r");

    int i = 0;
    while (!feof(f1))
    {   
        fgets(newbuf, 256, f1);
        sscanf(newbuf, "%[^:]", user);
        if (strcmp(buffer, user) == 0)
        {
            n = write(newsockfd, "1", 1);
            readPass(newsockfd, n, buffer, i);
            return 1;
        }
        else
        {
            i++;
        }
    }
    n = write(newsockfd, "Invalid username, please try again\n", 34);
    return 0;    
}



int main(int argc, char *argv[])
{
    pid_t cli2, cli3;
    int sockfd, newsockfd, portno, clilen;
    int cli_num = 0;
    int clients[3];
    char buffer[256];
    struct sockaddr_in serv_addr, cli_addr;
    int n;
    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_port = htons(portno);
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
    {
        error("ERROR on binding");
    }
    listen(sockfd, 5);
    clilen = sizeof(cli_addr);

    //cli2 = fork();
    //cli3 = fork();
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);

    if (newsockfd < 0) 
    {
        error("ERROR on accept");
    }

    readUser(newsockfd, n, buffer);
    return 0;
}

我的客户代码是:

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

void error(char *msg)
{
    perror(msg);
    exit(0);
}

void sendUser(int sockfd, int n, char buffer[], WINDOW *login)
{
    bzero(buffer, 256);
    getstr(buffer);
    n = write(sockfd, buffer, strlen(buffer));
    if (n = 0)
    {
        error("ERROR writing to socket");
    }
}

void sendPass(int sockfd, int n, char buffer[], WINDOW *login)
{
    bzero(buffer, 256);
    noecho();
    cbreak();

    int i = 0;
    while(1)
    {
        int temp = getch();
        if (temp == 10)
        {
            break;  
        }
        else
        {
            buffer[i] = temp;
            addch('*');
            i++;
        }
    }
    n = write(sockfd, buffer, strlen(buffer));
    if (n = 0)
    {
        error("ERROR writing to socket");
    }
}

int main(int argc, char *argv[])
{
    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;
    char buffer[256];
    if (argc < 3) 
    {
        fprintf(stderr, "usage %s hostname post\n", argv[0]);
        exit(0);
    }
    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");
    }

    char valid[1];
    WINDOW *login = initscr();

    int tries = 3;
    for (int i = 0; i<3; i++)
    {
        waddstr(login, "\nWelcome to Computer Science Department\n\n");
        waddstr(login, "Login: ");
        sendUser(sockfd, n, buffer, login);
        n = read(sockfd, valid, 1);

        if (strcmp(valid, "1") == 0)
        {
            valid[0] = 0;
            waddstr(login, "Password: ");
            sendPass(sockfd, n, buffer, login);
            n = read(sockfd, valid, 1);

            if (strcmp(valid,"1") == 0)
            {
                endwin();
                bzero(buffer, 256);
                n = read(sockfd, buffer, 255);
                if (n = 0)
                {
                    error("ERROR reading from socket");
                }
                printf("%s\n", buffer);
                break;
            }
            else
            {
                endwin();
                tries--;
                bzero(buffer, 256);
                n = read(sockfd, buffer, 255);
                if (n = 0)
                {
                    error("ERROR reading from socket");
                }
                printf("%s\n", buffer);
            }
        }
        else
        {
            endwin();
            tries--;
            bzero(buffer, 256);
            n = read(sockfd, buffer, 255);
            if (n = 0)
            {
                error("ERROR reading from socket");
            }
            printf("%s\n", buffer);
        }
    }
    if (strcmp(valid, "1") == 0)
    {
        return 0;
    }
    else
    {
        bzero(buffer, 256);
        n = read(sockfd, buffer, 255);
        if (n = 0)
        {
            error("ERROR reading from socket");
        }
        printf("%s\n", buffer);
    }
}

我的问题是: 键入用户名并按Enter键之后,客户端或服务器端均不会发生任何反应。为什么?

1 个答案:

答案 0 :(得分:0)

在客户端代码中调用endwin()之前,请先从服务器检查响应,即密码是否有效。如果无效,则可以重新输入两次或类似内容,然后发布“拒绝访问”消息。 您可以通过结合使用循环和操纵ncurses窗口来实现密码的三次输入,请参见以下伪代码:

//bool pw_valid=false; https://stackoverflow.com/questions/1921539/using-boolean-values-in-c
int pw_valid=0; // 0 is false and 1 is true

for(int i=0; i<3; i++)
  {
     manipulate curses screen to (re-)enter password; check if password is valid  (ask server, create new response on the server that verifies valid or invalid password check...) and set pw_valid accordingly;
     if(pw_valid==1){printw("Password is valid!\n"); break;}

  }

if(pw_valid==0) printw("Access denied!\n");
endwin();    //https://linux.die.net/man/3/endwin

关键是break;指令,您无需输入三次密码即可退出循环。

有关curses命令和curses C ++示例,另请参见 http://www.cs.ukzn.ac.za/~hughm/os/notes/ncurses.html http://www.cplusplus.com/articles/E6vU7k9E/#CURSES