服务器回射echo程序 是什么意思

服务器回射echo程序 是什么意思,第1张

下面将实现一个简单的TCP回射服务器,即从客户端收到什么数据,就发送什么数据。

[cpp] view plain copy

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <stdlib.h>

#define BUFFER_SIZE 1024

int main(int argc, char** argv)

{

if(argc != 2)

{

printf("Usage:\n%s <port>", argv[0])

return 0

}

struct sockaddr_in myAddr, clientAddr

int socketFd, clientFd

unsigned int clientAddrLen = sizeof(clientAddr)

int receivedLength

char buffer[BUFFER_SIZE]

memset(&clientAddr, 0, sizeof(clientAddr))

memset(&myAddr, 0, sizeof(myAddr))

myAddr.sin_family = AF_INET

myAddr.sin_port = htons(atoi(argv[1]))

myAddr.sin_addr.s_addr = htonl(INADDR_ANY)

socketFd = socket(AF_INET, SOCK_STREAM, 0)

bind(socketFd, (struct sockaddr*)&myAddr, sizeof(myAddr))

listen(socketFd, 5)

clientFd = accept(socketFd, (struct sockaddr *)&clientAddr, &clientAddrLen)

receivedLength = recv(clientFd, buffer, BUFFER_SIZE, 0)

buffer[receivedLength] = '\0'

printf("Received a message from %s:%u:\n%s\n"

, inet_ntoa(clientAddr.sin_addr)

, ntohs(clientAddr.sin_port),buffer)

send(clientFd, buffer, receivedLength, 0)

close(clientFd)

close(socketFd)

return 0

}

假设这个程序的名字是TcpServer,在编译好的可执行文件的目录下,输入:./TcpServer 2333启动服务器程序

然后使用netcat来向它发起来接:nc 127.0.0.1 2333

在netcat里输入一些字符,按回车以后,可以在TcpServer的输出中看到收到的数据,在netcat里可以看到服务器返回的数据。

也可以和《Linux网络编程(1)》里面的程序相互测试一下效果。

服务器程序

/* include udpservselect01 */

#include    "unp.h"

int

main(int argc, char **argv)

{

    int                    listenfd, connfd, udpfd, nready, maxfdp1

    char                mesg[MAXLINE]

    pid_t                childpid

    fd_set                rset

    ssize_t                n

    socklen_t            len

    const int            on = 1

    struct sockaddr_in    cliaddr, servaddr

    void                sig_chld(int)

        /* 4create listening TCP socket */

    listenfd = Socket(AF_INET, SOCK_STREAM, 0)

    bzero(&servaddr, sizeof(servaddr))

    servaddr.sin_family      = AF_INET

    servaddr.sin_addr.s_addr = htonl(INADDR_ANY)

    servaddr.sin_port        = htons(SERV_PORT)

    Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))

    Bind(listenfd, (SA *) &servaddr, sizeof(servaddr))

    Listen(listenfd, LISTENQ)

        /* 4create UDP socket */

    udpfd = Socket(AF_INET, SOCK_DGRAM, 0)

    bzero(&servaddr, sizeof(servaddr))

    servaddr.sin_family      = AF_INET

    servaddr.sin_addr.s_addr = htonl(INADDR_ANY)

    servaddr.sin_port        = htons(SERV_PORT)

    Bind(udpfd, (SA *) &servaddr, sizeof(servaddr))

/* end udpservselect01 */

/* include udpservselect02 */

    Signal(SIGCHLD, sig_chld)    /* must call waitpid() */

    FD_ZERO(&rset)

    maxfdp1 = max(listenfd, udpfd) + 1

    for (   ) {

        FD_SET(listenfd, &rset)

        FD_SET(udpfd, &rset)

        if ( (nready = select(maxfdp1, &rset, NULL, NULL, NULL)) < 0) {

            if (errno == EINTR)

                continue        /* back to for() */

            else

                err_sys("select error")

        }

        if (FD_ISSET(listenfd, &rset)) {

            len = sizeof(cliaddr)

            connfd = Accept(listenfd, (SA *) &cliaddr, &len)

    

            if ( (childpid = Fork()) == 0) {    /* child process */

                Close(listenfd)    /* close listening socket */

                str_echo(connfd)    /* process the request */

                exit(0)

            }

            Close(connfd)            /* parent closes connected socket */

        }

        if (FD_ISSET(udpfd, &rset)) {

            len = sizeof(cliaddr)

            n = Recvfrom(udpfd, mesg, MAXLINE, 0, (SA *) &cliaddr, &len)

            Sendto(udpfd, mesg, n, 0, (SA *) &cliaddr, len)

        }

    }

}

/* end udpservselect02 */

创建TCP套接

17~28 创建一个监听套接字并捆绑服务器到总所周知的端口,设置 SO_REUSEADDR套接字选项防止该端口上已有连接存在。

创建UDP套接字

30~38 还创建了一个UDP套接字捆绑于TCP套接字相同的端口,设置 SO_REUSEADDR套接字选项,因为TCP端口是独立于UDP端口的。

给SIGCHLD建立信号处理程序

42 因为TCP连接将由某个子程序处理。给出这个信号处理函数见下面。

准备调用select

44~45 我们给select初始化一个描述符集,并计算出我们等待的两个描述符的较大者。

调用select

47~54 我们调用select只是为了等待监听TCP套接字的可读条件或UDP套接字的可读条件。 既然我们的sig_chld信号处理函数可能中断我们对select的调用,我们于是需要处理EINTR错误。

处理新的客户端连接

56-66 当监听的TCP套接字可读时,我们accept一个新的客户连接,fork一个子程序,并在子程序进程中调用str_echo函数。

处理数据报的到达

68~74 如果UDP套接字可读,那么已有一个数据报到达。我们使用recvfrom读入它,再使用sendto把它发回客户端。

客户端程序(tcp和udp)

#include    "unp.h"

int

main(int argc, char **argv)

{

    int                    sockfd

    struct sockaddr_in    servaddr

    if (argc != 2)

        err_quit("usage: tcpcli <IPaddress>")

    sockfd = Socket(AF_INET, SOCK_STREAM, 0)

    bzero(&servaddr, sizeof(servaddr))

    servaddr.sin_family = AF_INET

    servaddr.sin_port = htons(SERV_PORT)

    Inet_pton(AF_INET, argv[1], &servaddr.sin_addr)

    Connect(sockfd, (SA *) &servaddr, sizeof(servaddr))

    str_cli(stdin, sockfd)        /* do it all */

    exit(0)

}

UDP客户端程序

#include    "unp.h"

int

main(int argc, char **argv)

{

    int                    sockfd

    struct sockaddr_in    servaddr

    if (argc != 2)

        err_quit("usage: udpcli <IPaddress>")

    bzero(&servaddr, sizeof(servaddr))

    servaddr.sin_family = AF_INET

    servaddr.sin_port = htons(SERV_PORT)

    Inet_pton(AF_INET, argv[1], &servaddr.sin_addr)

    sockfd = Socket(AF_INET, SOCK_DGRAM, 0)

    dg_cli(stdin, sockfd, (SA *) &servaddr, sizeof(servaddr))

    exit(0)

}

信号处理程序

#include    "unp.h"

void

sig_chld(int signo)

{

    pid_t    pid

    int        stat

    while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0)

        printf("child %d terminated\n", pid)

    return

}

UDP的回射服务器程序:dg_echo函数

#include <unp.h>

void dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen)

{

    int     n

    socklen_t    len

    char mesg[MAXLINE]

    for()

    {

        len = clilen

        n = Recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len)

        Sendto(sockfd, mesg, n, 0, pcliaddr, len)

    }

}

UDP的回射客户程序:dg_cli函数

#include <unp.h>

void dg_cli(FILE *fp, int sockfd, const SA* pservaddr, socklen_t servlen)

{

    int     n

    char    sendline[MAXLINE], recvline[MAXLINE+1]

    while(Fgets(sendline, MAXLINE, fp) != NULL)

    {

        Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen)

        n = Recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL)

        recvline[n] = '\0'

        Fputs(recvline, stdout)

    }

}

简单的写了一下,没有加注释,应该很好理解,满意的话请采纳

#include <stdio.h>

#include <sys/socket.h>

#include <pthread.h>

void *thread(void *st)

int main(int argc, char *argv[])

{

pthread_t tid

int ret, fd

struct sockaddr_in info

fd = socket(AF_INET, SOCK_STREAM, 0)

if(fd <0)

goto socket_error

{

int var = 1

setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &var, sizeof(var))

}

info.sin_family = AF_INET

info.sin_port = htons(80)

info.sin_addr.s_addr = 0

ret = bind(fd, (void *)&info, sizeof(info))

if(ret)

goto bind_error

ret = listen(fd, 10)

if(ret)

goto listen_error

while(1)

{

clientfd = accept(fd, NULL, NULL)

pthread_create(&tid, NULL, thread, (void *)clientfd)

}

return 0

socket_error:

printf("socket error!\n")

return -1

bind_error:

printf("bind error!\n")

return -2

lister_error:

printf("lister error!\n")

return -2

}

void *thread(void *st)

{

int ret, rd

char buf[BUFSIZE]

int clientfd = (int)st

rd = read(clientfd, buf, sizeof(buf))

if(rd <0)

{

printf("read error!\n")

return

}

write(clientfd, "shou dao!", 9)

close(clientfd)

}


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/109560.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-03-11
下一篇2023-03-11

发表评论

登录后才能评论

评论列表(0条)

    保存