5-TCP Client&Server Example

Please indicate the source: http://blog.csdn.net/gaoxiangnumber1

Welcome to my github: https://github.com/gaoxiangnumber1

  • Our echo server performs the following steps:
    1. The client reads a line of text from its standard input and writes the line to the server.
    2. The server reads the line from its network input and echoes the line back to the client.
    3. The client reads the echoed line and prints it on its standard output.

  • We show two arrows between the client and server, but this is really one full-duplex TCP connection.

5.2 TCP Echo Server: ‘main’ Function

Create socket, bind server’s well-known port 9–15

  • An Internet socket address structure is filled in with the wildcard address (INADDR_ANY) and the server’s well-known port(SERV_PORT). Binding the wildcard address will accept a connection destined for any local interface, in case the system is multihomed.
  • Our TCP port number should be greater than 1023(we do not need a reserved port), greater than 5000(to avoid conflict with the ephemeral ports allocated by many Berkeley-derived implementations), less than 49152(to avoid conflict with the “correct” range of ephemeral ports), and it should not conflict with any registered port.

Wait for client connection to complete 17–18

  • The server blocks in the call to accept, waiting for a client connection to complete.

Concurrent server 19–24

  • For each client, fork spawns a child, and the child handles the new client. The child closes the listening socket and the parent closes the connected socket. The child then calls str_echo to handle the client.

5.3 TCP Echo Server: ‘str_echo’ Function

  • str_echo reads data from the client and echoes it back to the client.

Read a buffer and echo the buffer 8–9

  • read reads data from the socket and the line is echoed back to the client by writen. If the client closes the connection(the normal scenario), the receipt of the client’s FIN causes the child’s read to return 0. This causes the str_echo function to return, which terminates the child.
/*
void str_echo(int sockfd);
void Writen(int fd, void *ptr, int nbytes);
int writen(int fd, const void *vptr, int n)
*/

#include <stdio.h>              // printf()
#include <stdlib.h>         // exit()
#include <sys/types.h>
#include <sys/socket.h> // socket(), bind(), listen(), accept()
#include <strings.h>            // bzero()
#include <arpa/inet.h>      // htonl(), htons()
#include <unistd.h>         // fork(), close(), read(), write()
#include <errno.h>          // errno

#define     LISTENQ     32
#define     MAXLINE     4096
#define     SERV_PORT   7188

void Exit(char *string)
{
    printf("%s\n", string);
    exit(1);
}

int Socket(int family, int type, int protocol)
{
    int n;
    if((n = socket(family, type, protocol)) < 0)
    {
        Exit("socket error");
    }
    return n;
}

void Bind(int fd, const struct sockaddr *sa, socklen_t salen)
{
    if(bind(fd, sa, salen) < 0)
    {
        Exit("bind error");
    }
}

void Listen(int fd, int backlog)
{
    if(listen(fd, backlog) < 0)
    {
        Exit("listen error");
    }
}

int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr)
{
    printf("Enter accept:\n");
    int n;
again:
    if((n = accept(fd, sa, salenptr)) < 0)
    {
        // EPROTO: Protocol error; ECONNABORTED: Connection aborted
        if(errno == EPROTO || errno == ECONNABORTED)
        {
            printf("Enter accept: errno == EPROTO || errno == ECONNABORTED\n");
            goto again;
        }
        else
        {
            Exit("accept error");
        }
    }
    return n;
}

pid_t Fork()
{
    pid_t pid;
    if((pid = fork()) == -1)
    {
        Exit("fork error");
    }
    return pid;
}

void Close(int fd)
{
    if(close(fd) == -1)
    {
        Exit("close error");
    }
}

int writen(int fd, const void *vptr, int n)
{
    printf("writen Enter:\n");
    int nleft = n;
    int nwritten;
    const char *ptr = vptr;

    while(nleft > 0)
    {
        printf("writen Enter: writing in while(nleft > 0) loop.\n");
        if((nwritten = write(fd, ptr, nleft)) <= 0)
        {
            if(nwritten < 0 && errno == EINTR)
            {
                printf("writen Enter: Interrupt occurs\n");
                nwritten = 0;       /* and call write() again */
            }
            else
            {
                return -1;          /* error */
            }
        }
        nleft -= nwritten;
        ptr += nwritten;
    }
    return n;
}

void Writen(int fd, void *ptr, int nbytes)
{
    if(writen(fd, ptr, nbytes) != nbytes)
    {
        Exit("writen error");
    }
}

void str_echo(int sockfd)
{
    printf("str_echo Enter:\n");
    int n;
    char buf[MAXLINE];

again:
    while((n = read(sockfd, buf, MAXLINE)) > 0)
    {
        printf("str_echo Enter: Writen(sockfd, buf, n);\n");
        Writen(sockfd, buf, n);
    }
    if(n < 0 && errno == EINTR)
    {
        printf("str_echo: EINTR. continue\n");
        goto again;
    }
    else if(n < 0)
    {
        Exit("str_echo: read error");
    }
}

int main()
{
    int listenfd, connfd;
    pid_t childpid;
    socklen_t clilen;
    struct sockaddr_in cliaddr, servaddr;

    listenfd = Socket(AF_INET, SOCK_STREAM, 0);
    printf("Socket success.\n");

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    printf("Bind success\n");

    Listen(listenfd, LISTENQ);
    printf("Listen success\n");

    for(;;)
    {
        printf("Enter for(;;) loop:\n");
        clilen = sizeof(cliaddr);
        connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
        printf("Accept success.\n");
        if((childpid = Fork()) == 0)
        {
            printf("Child Enter\n");
            Close(listenfd);
            str_echo(connfd);
            printf("Child Exit\n");
            exit(0);  // Auto Close(connfd);
        }
        Close(connfd);
    }
}

5.4 TCP Echo Client: ‘main’ Function

  • Figure 5.4 shows the TCP client main function.

Create socket, fill in Internet socket address structure 9–13

  • A TCP socket is created and an Internet socket address structure is filled in with the server’s IP address and port number. We take the server’s IP address from the command-line argument and the server’s well-known port (SERV_PORT) is from our unp.h header.

Connect to server 14–15

  • connect establishes the connection with the server. The function str_cli(Figure 5.5) handles the rest of the client processing.

5.5 TCP Echo Client: ‘str_cli’ Function

  • This function, shown in Figure 5.5, handles the client processing loop: It reads a line of text from standard input, writes it to the server, reads back the server’s echo of the line, and outputs the echoed line to standard output.

Read a line, write to server 6–7

  • fgets reads a line of text and writen sends the line to the server.

Read echoed line from server, write to standard output 8–10

  • readline reads the line echoed back from the server and fputs writes it to standard output.

Return to main 11–12

  • The loop terminates when fgets returns a null pointer, which occurs when it encounters either an end-of-file (EOF) or an error. Our Fgets wrapper function checks for an error and aborts if one occurs, so Fgets returns a null pointer only when an end-of-file is encountered.
/*
void Inet_pton(int family, const char *strptr, void *addrptr);
void Connect(int fd, const struct sockaddr *sa, socklen_t salen);
void str_cli(FILE *fp, int sockfd);
char* Fgets(char *ptr, int n, FILE *fp);
void Fputs(const char *ptr, FILE *fp);
static int my_read(int fd, char *ptr);
int readline(int fd, void *vptr, int maxlen);
int Readline(int fd, void *ptr, int maxlen);
*/

#include <stdio.h>              // printf(), fgets(), ferror(), fputs()
#include <stdlib.h>         // exit()
#include <sys/types.h>
#include <sys/socket.h> // socket(), connect()
#include <strings.h>            // bzero()
#include <string.h>         // strlen()
#include <arpa/inet.h>      // htons(), inet_pton()
#include <unistd.h>         // read(), write()
#include <errno.h>          // errno

#define MAXLINE     4096
#define SERV_PORT   7188

void Exit(char *string)
{
    printf("%s\n", string);
    exit(1);
}

int Socket(int family, int type, int protocol)
{
    int n;
    if((n = socket(family, type, protocol)) < 0)
    {
        Exit("socket error");
    }
    return n;
}

void Inet_pton(int family, const char *strptr, void *addrptr)
{
    if(inet_pton(family, strptr, addrptr) <= 0)
    {
        Exit("inet_pton error");
    }
}

void Connect(int fd, const struct sockaddr *sa, socklen_t salen)
{
    if(connect(fd, sa, salen) < 0)
    {
        Exit("connect error");
    }
}

char* Fgets(char *ptr, int n, FILE *fp)
{
    char *rptr;
    if((rptr = fgets(ptr, n, fp)) == NULL && ferror(fp))
    {
        Exit("fgets error");
    }
    return rptr;
}

int writen(int fd, const void *vptr, int n)
{
    int nleft = n;
    int nwritten;
    const char *ptr = vptr;

    while(nleft > 0)
    {
        if((nwritten = write(fd, ptr, nleft)) <= 0)
        {
            if(nwritten < 0 && errno == EINTR)
            {
                nwritten = 0;       /* and call write() again */
            }
            else
            {
                return -1;          /* error */
            }
        }
        nleft -= nwritten;
        ptr += nwritten;
    }
    return n;
}

void Writen(int fd, void *ptr, int nbytes)
{
    if(writen(fd, ptr, nbytes) != nbytes)
    {
        Exit("writen error");
    }
}

static int  read_cnt = 0;
static char *read_ptr = NULL;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值