Linux平台C语言Socket编程练习之线程专用数据TSD实现

作者: 分类: 学习记录 评论: 暂无 时间: 2016-11-26 浏览: 1,624 次

0x00 要求

采用多线程并发服务器技术,服务器可以同时接受多个客户的请求。具体要求如下:

服务端

接收并显示与之连接的客户端的名称;

接收客户端发来的字符串,显示出来,并对字符串做反转处理,最后将处理后的字符串发回给客户;

在每个用户退出时要显示该用户输入的所有信息。

客户端

根据客户输入的服务器IP地址,向服务器发起建立连接的请求;

接收客户输入的客户端名称,并把该客户端名称发给服务器;

接收客户输入的字符串,将字符串发送给服务器;

接收服务器发回的反转处理后的字符串并显示。继续接受客户输入的字符串,直到用户输入quit时退出。

0x01 代码

服务端

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


#define PORT 1234
#define BACKLOG 5
#define MAXDATASIZE 100

void process_cli(int connfd,struct sockaddr_in client,char cli_input[]);
void* function(void* arg);
struct ARG
{
    int connfd;
    char cli_input[1000];
    struct sockaddr_in client;
};

int main()
{
    int listenfd;
    int connfd;
    pthread_t tid;
    socklen_t client_len;
    struct ARG *arg;
    struct sockaddr_in server;
    struct sockaddr_in client;

    if((listenfd=socket(AF_INET,SOCK_STREAM,0))==-1)
    {
        perror("socket() failed.");
        exit(1);
    }

    int opt=SO_REUSEADDR;
    setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
    bzero(&server,sizeof(server));
    server.sin_family=AF_INET;
    server.sin_port=htons(PORT);
    server.sin_addr.s_addr=htonl(INADDR_ANY);

    if(bind(listenfd,(struct sockaddr *)&server,sizeof(server))==-1)
    {
        perror("bind() failed.");
        exit(1);
    }

    if(listen(listenfd,BACKLOG)==-1)
    {
        perror("listen() failed.");
        exit(1);
    }

    client_len=sizeof(client);

    while(1)
    {
        if((connfd=accept(listenfd,(struct sockaddr *)&client,&client_len))==-1)
        {
            perror("accept() failed.");
            printf("runed here!\n");
            exit(1);
        }

        arg=(struct ARG *)malloc(sizeof(struct ARG));
        arg->connfd=connfd;

        memcpy((void *)&arg->client,&client,sizeof(client));

        if(pthread_create(&tid,NULL,function,(void *)arg))
        {
            perror("pthread_create() failed.");
            exit(1);
        }
    }
    close(listenfd);
    return 0;
}

void process_cli(int connfd,struct sockaddr_in client,char cli_input[])
{
    ssize_t send_num;
    ssize_t recv_num;
    char send_buf[MAXDATASIZE];
    char recv_buf[MAXDATASIZE];
    char client_name[MAXDATASIZE];
    char wel_msg[]="[!] Welcome,you can input 'quit' to exit :)  ";


    printf("[!] You got a connection from client IP: <%s> PORT: <%d> \n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));

    if((send(connfd,wel_msg,strlen(wel_msg),0))==-1)
    {
        perror("send welcome messages fail.");
        exit(1);
    }

    if((recv_num=recv(connfd,client_name,MAXDATASIZE,0))==-1)
    {
        perror("recv() failed.");
        close(connfd);
    }

    if(recv_num==0)
    {
        printf("[!] Client disconnected.\n");
        close(connfd);
    }

    client_name[recv_num-1]='\0';
    printf("[*] Client name: <%s> \n",client_name);

    while(1)
    {
        if((recv_num=recv(connfd,recv_buf,MAXDATASIZE,0))==-1)
        {
            perror("recv() error.");
            exit(1);
        }

        recv_buf[recv_num]='\0';
        printf("[*] Received string: '%s' from client: <%s> \n ",recv_buf,client_name);

        int cur_save_len=strlen(cli_input);
        while(recv_num--)
        {
            cli_input[cur_save_len+recv_num]=recv_buf[recv_num];
        }

        size_t len=strlen(recv_buf);
        for(int i=0; i<(len/2); ++i)
        {
            char tmp=recv_buf[i];
            recv_buf[i]=recv_buf[len-1-i];
            recv_buf[len-1-i]=tmp;
        }

        strcpy(send_buf,recv_buf);
        printf("[>] Send reverse string: '%s' to client: <%s> \n",send_buf,client_name);

        if((send_num=send(connfd,send_buf,MAXDATASIZE,0))==-1)
        {
            perror("send() error.");
            exit(1);
        }

        if(!strcmp(send_buf,"tiuq"))
        {
            printf("[!] Received a total of string: '%s' from client: <%s> and the client have disconnected! \n",cli_input,client_name);
            break;
        }
    }
    close(connfd);
}

void* function(void* arg)
{
    struct ARG *info;
    info=(struct ARG *)arg;
    process_cli(info->connfd,info->client,info->cli_input);
    free(arg);
    pthread_exit(NULL);
}

客户端

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

#define PORT 1234
#define MAXDATASIZE 100

int main(int argc,char *argv[])
{
    int sockfd;
    ssize_t send_num;
    ssize_t recv_num;
    char wel_msg[MAXDATASIZE];
    char cli_name[MAXDATASIZE];
    char recv_buf[MAXDATASIZE];
    char send_buf[MAXDATASIZE];
    struct hostent *he;
    struct sockaddr_in server;
    if(argc!=2)
    {
        printf("Usage:%s <IP Adress>\n",argv[0]);
        exit(1);
    }
    if((he=gethostbyname(argv[1]))==NULL)
    {
        printf("gethostbyname() failed.");
        exit(1);
    }
    if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
    {
        printf("socket() failed.");
        exit(1);
    }
    bzero(&server,sizeof(server));
    server.sin_family=AF_INET;
    server.sin_port=htons(PORT);
    server.sin_addr=*((struct in_addr *)he->h_addr);

    if(connect(sockfd,(struct sockaddr *)&server,sizeof(server))==-1)
    {
        printf("connect() failed.");
        exit(1);
    }
    if ((recv(sockfd,wel_msg,MAXDATASIZE,0))==-1)
    {
        perror("[!] Receive welcome message fail.");
        exit(1);
    }
    wel_msg[sizeof(wel_msg)]='\0';
    printf("%s\n", wel_msg);
    printf("[*] Input client name:");
    scanf("%s",cli_name);
    if((send_num=send(sockfd,cli_name,MAXDATASIZE,0))==-1)
    {
        perror("send() error.");
        exit(1);
    }

    while(1)
    {
        printf("[*] Input string:");
        scanf("%s",send_buf);
        send_buf[strlen(send_buf)]='\0';

        if((send_num=send(sockfd,send_buf,MAXDATASIZE,0))==-1)
        {
            perror("send() error.");
            exit(1);
        }

        if((recv_num=recv(sockfd,recv_buf,MAXDATASIZE,0))==-1)
        {
            perror("recv() error.");
            exit(1);
        }

        printf("[>] Received reverse string:%s\n",recv_buf);
        if(!strcmp(recv_buf,"tiuq"))
        {
            break;
        }
    }
    close(sockfd);
    return 0;
}

0x02 演示

服务端

多线程TSD服务端.gif

客服端1

多线程TSD客户端1.gif

客户端2

多线程TSD客户端2.gif

转载请注明来自精灵博客的Linux平台C语言Socket编程练习之线程专用数据TSD实现,否则保留追究文章版权的权利!

订阅本站(RSS)

添加新评论