回声服务器'有时'终止时没有任何签名

时间:2017-04-10 15:03:20

标签: c linux sockets

我在Linux套接字编程上遇到了问题,我无法理解这种情况。

它是一个简单的echo服务器 - 客户端程序对。

这是我编程的:

这是echoClient。

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

#define RCV_BUF_SIZE 512    //receive buffer size

int main(int argc, char *argv[])
{
    int sock;   //socket
    struct sockaddr_in echoServAddr;//server socket address struct
    unsigned short echoServPort;    //server port
    char *servIP;   //server address
    char *echoString;   //sending msg
    char echoBuffer[RCV_BUF_SIZE];  //receive buffer
    unsigned int echoStringLen = 0; //msg length
    int bytesRcvd, totalBytesRcvd; //received bytes, total bytes received

    if((argc < 2) || (argc > 3)) //if there are no right arguements, throw error and exit program
    {
        printf("Usage : %s <Server IP> [<Echo Port>]\n", argv[0]);
        exit(1);
    }

    servIP = argv[1];

    if(argc == 3)//user defined exact port
    {
        echoServPort = atoi(argv[2]);
    }
    else//user didnt defined, use well-known port
    {
        echoServPort = 7;
    }

    if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)//if socket creation failed
    {
        printf("socket() failed\n");
        exit(1);
    }

    memset(&echoServAddr, 0, sizeof(echoServAddr));//memory reset
    echoServAddr.sin_family = AF_INET;  //setting server's address
    echoServAddr.sin_addr.s_addr = inet_addr(servIP);
    echoServAddr.sin_port = htons(echoServPort);

    if(connect(sock, (struct sockaddr*)&echoServAddr, sizeof(echoServAddr)) < 0)//connect try, -1 if failed
    {
        printf("connect() failed\n");
        perror("error is : ");
        exit(1);
    }


    printf("to exit, type \"/exit\"\n");
    while(1)
    {

        printf("insert echo word : ");
        echoString = gets();
        echoStringLen = strlen(echoString);

        if(echoStringLen > 512)//msg's length
        {
            printf("echo word is too long! (must be shorter than 512)\n");
            echoStringLen = 0;
            continue;
        }

        if(!strcmp(echoString, "\/exit"))
        {
            if(send(sock, echoString, echoStringLen, 0) != echoStringLen)//send to server, if sended bytes are smaller than string length
            {
                printf("sending close socket  failed\n");
                exit(1);
            }

            printf("clossing socket...\n");
            break;
        }

        if(send(sock, echoString, echoStringLen, 0) != echoStringLen)//send to server, if sended bytes are smaller than string length
        {
            printf("send() failed\n");
            exit(1);
        }

        totalBytesRcvd = 0;

        while(totalBytesRcvd < echoStringLen)//while received bytes are shorter than msg's length
        {
            if((bytesRcvd = recv(sock, echoBuffer, RCV_BUF_SIZE-1, 0)) <= 0)//-1 for null char
            {
                printf("recv() failed");
                exit(1);
            }

            totalBytesRcvd += bytesRcvd;    //++ total bytes received
            echoBuffer[bytesRcvd] = '\0';   //set last char to null cahr
            printf(echoBuffer); //print received buffer
        }
        printf("\n");
    }


    close(sock);
    exit(0);
}

,这是echoServer。

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

#define RCV_BUF_SIZE 512    //receive buffer size
#define MAX_BACKLOG 5

int main(int argc, char *argv[])
{
    struct sockaddr_in echoServAddr, echoClntAddr;  //define socket address(server, client)
    int servSock, clntSock; //socket 
    unsigned short echoServPort;    //port
    unsigned int clntLen;   //client address length
    char echoBuffer[RCV_BUF_SIZE];  //receive buffer
    int recvMsgSize;    //received msg size

    printf("echooo!\n\n");

    echoServPort = atoi(argv[1]);

    if((servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) //socket creation failed
    {
        printf("socket() failed\n");
        exit(1);
    }

    if(argc != 2)   //if there are no right arguements, throw error and end program
    {
        printf("Usage : %s port\n", argv[0]);
        exit(1);
    }

    memset(&echoServAddr, 0, sizeof(echoServAddr));     //memory reset
    echoServAddr.sin_family = AF_INET;          //define server address type
    echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    echoServAddr.sin_port = htons(echoServPort);



    if(bind(servSock, (struct sockaddr *)&echoServAddr, sizeof(echoServAddr))<0)//bind try, return -1 if error
    {
        printf("bind() failed, socket number : %d\n", servSock);
        perror("Error : ");
        exit(1);
    }

    if(listen(servSock, MAX_BACKLOG) < 0)//listen try, return -1 if error
    {
        printf("listen(failed\n");
        exit(1);
    }

    while(1)
    {
        clntLen = sizeof(echoClntAddr);

        if((clntSock = accept(servSock, (struct sockaddr*)&echoClntAddr, &clntLen))<0)//accept try, return -1 if error
        {
            printf("recv() failed\n");
            exit(1);
        }

        while(1)
        {


            if((recvMsgSize = recv(clntSock, echoBuffer, RCV_BUF_SIZE, 0)) < 0)//recv try, return -1 if error
            {
                printf("recv() failed\n");
                exit(1);
            }

            if(!strcmp(echoBuffer, "\/exit"))
            {

                break;
            }

            if(send(clntSock, echoBuffer, recvMsgSize, 0) != recvMsgSize)//send try, if sended bytes are shorter than recved bytes: throw error
            {
                printf("send() failed\n");
                exit(1);
            }

        }

    }
    close(clntSock);
}

这是简单的描述。

  1. 服务器启动并继续收听。

  2. 客户端连接。

  3. 客户端从用户获取echo字,并将其发送到服务器。

  4. 服务器接收并返回它们。

  5. 重复,但一旦用户输入&#34; /退出&#34;,客户端发送&#34; /退出&#34;,并关闭套接字。

  6. 并且服务器收到&#34; / exit&#34;,服务器关闭套接字并退出。

  7. 但是,这就是问题所在。 服务器可以向客户端发送回显字,但是服务器进程有时会发送回#。当客户端发送&#34; /退出&#34;时终止,没有任何符号。我不知道为什么,但并非总是如此。

    我试图将perror()放在内部while循环的末尾,或者外部while循环,但我无法弄明白。

    如果有人帮我解决这个服务器问题,我会很高兴。

0 个答案:

没有答案