Linux网络编程——tcp实例

题目

1、通过TCP协议实现多个client端可以并发连接到server,client可获得server指定目录下的文件列表。

/*
 * client.c
 *
 *  Created on: 2016年11月3日
 *      Author: Administrator
 */
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define BUFSIZE 10240

int socket_connect(const char*hostname, int port)
{
    int client_st = socket(AF_INET, SOCK_STREAM, 0);
    if (client_st == -1)
    {
        printf("socket failed %s\n", strerror(errno));
        return -1;
    }
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = inet_addr(hostname);

    if (connect(client_st, (struct sockaddr*) &addr, sizeof(addr)) == -1)
    {
        printf("connect failed %s\n", strerror(errno));
        return -1;
    } else
    {
        printf("connect to %s:%d\n", hostname, port);
        return client_st;
    }
}

int socket_send_dir(int client_st, const char *dir)
{
    int rc = send(client_st, dir, strlen(dir), 0);
    if (rc <= 0)
    {
        printf("send failed %s\n", strerror(errno));
        return rc;
    }

    char *buf = malloc(BUFSIZE);
    memset(buf, 0, BUFSIZE);
    rc = recv(client_st, buf, BUFSIZE, 0);
    if (rc <= 0)
    {
        printf("recv failed %s\n", strerror(errno));
        return rc;
    }else
    {
        printf("%s\n", buf);//如果接收到来自server端的数据,将数据打印到屏幕
    }

    free(buf);

    return rc;
}

int main(int arg, char*args[])
{
    if (arg < 3)
    {
        printf("usage:client hostname port\n");
        return 0;
    }
    int iport = atoi(args[2]);
    if (iport == 0)
    {
        printf("port %d is invaild\n", iport);
        return 0;
    }

    int client_st = socket_connect(args[1], iport);
    if (client_st == -1)
    {
        printf("socket_connect failed\n");
        return 0;
    }

    char buf[200];
    while (1)
    {
        memset(buf, 0, sizeof(buf));
        read(STDIN_FILENO, buf, sizeof(buf));
        if (strncmp(buf, "exit",4) == 0)
            break;

        buf[strlen(buf) - 1] = 0;

        if (strlen(buf) == 0)
            continue;

        if (socket_send_dir(client_st, buf) <= 0)
            break;
    }
    close(client_st);

    return EXIT_SUCCESS;
}

/*
 ============================================================================
 Name        : CS-opendir.c
 Author      : Allen
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define BUFSIZE 10240

int socket_create(int port)
{
    int st=socket(AF_INET,SOCK_STREAM,0);
    int on = 1;
    if (setsockopt(st, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
    {
        printf("setsockopt failed %s\n", strerror(errno));
        return 0;
    }
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if ((bind(st, (struct sockaddr*) &server_addr, sizeof(server_addr))) == -1)
    {
        printf("bind failed %s\n", strerror(errno));
        return -1;
    }
    if ((listen(st, 20)) == -1)
    {
        printf("listen failed %s\n", strerror(errno));
        return -1;
    }
    return st;
}

int socket_accept(int listen_st)
{
    struct sockaddr_in client_addr;
    socklen_t len = sizeof(client_addr);
    memset(&client_addr, 0, sizeof(client_addr));

    int client_st = accept(listen_st, (struct sockaddr*) &client_addr, &len);
    if (client_st == -1)
    {
        printf("accpet failed %s\n", strerror(errno));
        return -1;
    } else
    {
        printf("accept by %s\n", inet_ntoa(client_addr.sin_addr));
    }
    return client_st;
}

void getdir(const char*dirname, char*buf)
{
    DIR *dp;
    dp = opendir(dirname);
    if (dp == NULL)
    {
        printf("opendir failed %s\n", strerror(errno));
        return;
    }
    struct dirent *dirp;

    char tmp[200];
    while ((dirp = readdir(dp)) != NULL)
    {
        memset(tmp, 0, sizeof(tmp));
        sprintf(tmp, "%s ", dirp->d_name);
        strcat(buf, tmp);
    }
    closedir(dp);
    return;
}

int socket_recv(int client_st)
{
    char recvbuf[200];
    memset(recvbuf, 0, sizeof(recvbuf));
    char *sendbuf = malloc(BUFSIZE);
    memset(sendbuf, 0, BUFSIZE);

    int rc = recv(client_st, recvbuf, sizeof(recvbuf), 0);
    printf("收到客户端的消息是:%s\n", recvbuf);
    if (rc <= 0)
    {
        printf("recv failed %s\n", strerror(errno));
    } else
    {
        getdir(recvbuf, sendbuf);
        rc = send(client_st, sendbuf, strlen(sendbuf), 0);
        if (rc <= 0)
        {
            printf("send failed %s\n", strerror(errno));
        }
    }
    free(sendbuf);
    //close(client_st);
    return rc;
}

int setnonblocking(int st) //将socket设置为非阻塞
{
    int opts = fcntl(st, F_GETFL);
    if (opts < 0)
    {
        printf("fcntl failed %s\n", strerror(errno));
        return 0;
    }
    opts = opts | O_NONBLOCK;
    if (fcntl(st, F_SETFL, opts) < 0)
    {
        printf("fcntl failed %s\n", strerror(errno));
        return 0;
    }
    return 1;
}

void run(int port)
{
    int listen_st = socket_create(port);
    setnonblocking(listen_st);

    struct epoll_event ev, events[200];
    int epfd = epoll_create(200);
    ev.data.fd = listen_st;
    ev.events = EPOLLIN | EPOLLERR | EPOLLHUP;
    epoll_ctl(epfd, EPOLL_CTL_ADD, listen_st, &ev);

    int st;
    while (1)
    {
        int nfds = epoll_wait(epfd, events, 200, -1);
        if (nfds == -1)
        {
            printf("epoll_wait failed %s\n", strerror(errno));
            break;
        }
        int i = 0;
        for (; i < nfds; i++)
        {
            if (events[i].data.fd < 0)
                continue;
            if (events[i].data.fd == listen_st)
            {
                st = socket_accept(listen_st);
                if (st > 0)
                {
                    setnonblocking(st);
                    ev.data.fd = st;
                    ev.events = EPOLLIN | EPOLLERR | EPOLLHUP;
                    epoll_ctl(epfd, EPOLL_CTL_ADD, st, &ev);
                    continue;
                }

            }
            if (events[i].events & EPOLLIN)
            {
                st = events[i].data.fd;
                if (socket_recv(st) <= 0)
                {
                    close(st);
                    events[i].data.fd = -1;
                }
            }
            if (events[i].events & EPOLLERR)
            {
                st = events[i].data.fd;
                close(st);
                events[i].data.fd = -1;
            }
            if (events[i].events & EPOLLHUP)
            {
                st = events[i].data.fd;
                close(st);
                events[i].data.fd = -1;
            }
        }
    }
    close(epfd);
}

int main(int arg, char*args[])
{
    if (arg < 2) //如果没有参数,main函数退出
    {
        printf("usage:server port\n");
        return EXIT_SUCCESS;
    }

    int iport = atoi(args[1]); //将第一个参数转化为端口号
    if (iport == 0)
    {
        printf("port %d is invalid\n", iport);
        return EXIT_SUCCESS;
    }
    run(iport);
    return EXIT_SUCCESS;
}

.SUFFIXES: .c .o

CC=gcc

SRCS1=server.c
SRCS2=client.c

OBJS1=$(SRCS1:.c=.o)
OBJS2=$(SRCS2:.c=.o)
EXEC1=server
EXEC2=client

all: $(OBJS1) $(OBJS2)
    $(CC) -o $(EXEC1) $(OBJS1)
    $(CC) -o $(EXEC2) $(OBJS2)
    @echo '-------------ok--------------'

.c.o: 
    $(CC) -Wall -g -o $@ -c $<

clean:
    rm -f $(OBJS1) $(OBJS2)
    rm -f core*

运行结果

server
Linux网络编程——tcp实例_第1张图片
client1
Linux网络编程——tcp实例_第2张图片
client2
Linux网络编程——tcp实例_第3张图片

今天没时间为代码注释啦,改天补齐.

你可能感兴趣的:(Linux网络编程)