基于 TCP 协议的并发服务器程序

服务端:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <netdb.h>
#include <pthread.h>

//线程执行函数,负责读写
void *thr_fn ( void *arg )
{
    int size, j;
    char recv_buf[1024];
    int *parg = ( int * ) arg;
    int new_fd = *parg;

    while ( ( size = read ( new_fd, recv_buf, sizeof ( recv_buf ) ) ) > 0 ) {
        if ( recv_buf[0] == '@' ) {
            break;
        }

        printf ( "Message from client(%d): %s\n", size, recv_buf );

        for ( j = 0; j < size; ++j )
            recv_buf[j] = toupper(recv_buf[j]);
        write(new_fd,recv_buf,size);
        }
        close(new_fd);
        return 0;
}

int main(int argc, char *argv[]){
   socklen_t clt_addr_len;
    int listen_fd;
    int com_fd;
    int ret;
    int i;
    static char recv_buf[1024];
    int len;
    int port;
    pthread_t tid;

    struct sockaddr_in clt_addr;
    struct sockaddr_in srv_addr;
    //服务器端运行时要给出端口信息,该端口为监听端口
    if(argc != 2){
        printf("Usage:%s port\n",argv[0]);
        return -1;
    }

    //获得输入的端口
    port = atoi(argv[1]);

    //创建套接字用于服务器的监听
    listen_fd = socket(PF_INET,SOCK_STREAM,0);
    if(listen_fd < 0){
        perror("cannot create listening socket");
        return -1;
    }

    //填充关于服务器的套接字信息
    memset(&srv_addr,0,sizeof(srv_addr));
    srv_addr.sin_family = AF_INET;
    srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    srv_addr.sin_port = htons(port);

    //将服务器和套接字绑定
    ret = bind(listen_fd,(struct sockaddr *)&srv_addr,sizeof(srv_addr));
    if(ret == -1){
        perror("cannot bind server socket");
        close(listen_fd);
        return -1;
    }

    //监听指定端口
    ret = listen(listen_fd,5);
    if(ret == -1){
        perror("cannot listen the client connect request");
        close(listen_fd);
        return -1;
    }

    /*
        对每个连接来的客户端创建一个线程,单独与其进行通信,
        首先调用 read 函数读取客户端发送来的信息
        将其转化成大写后发送回客户端
        当输入"@"时,程序退出
    */
    while(1){
        len = sizeof(clt_addr);
        com_fd = accept(listen_fd,(struct sockaddr *)&clt_addr,&len);
        if(com_fd < 0){
            if(errno == EINTR)
                continue;
            else{
                perror("cannot accept client connect request");
                close(listen_fd);
                return -1;
            }
        }
        printf("com_fd = %d\n",com_fd); //打印建立连接的客户端产生的套接字
        if((pthread_create(&tid,NULL,thr_fn,&com_fd)) == -1){
            perror("pthread_create error");
            close(listen_fd);
            close(com_fd);
            return -1;
        }
    }
    return 0;
}

客户端:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
#include <unistd.h>

int main(int argc, char**argv){
    int connect_fd;
    int ret;
    char snd_buf[1024];
    int i;
    int port;
    int len;
    static struct sockaddr_in srv_addr;
    //客户端运行需要给出具体的连接地址和端口
    if(argc != 3){
        printf("Usage: %s server_ip_address port\n",argv[0]);
        return -1;
    }
    //获得输入的端口
    port = atoi(argv[2]);

    //创建套接字用于客户端的连接
    connect_fd = socket(PF_INET,SOCK_STREAM,0);
    if(connect_fd < 0)
    {
        perror("cannot create communication socket");
        return 1;
    }

    //填充关于服务器的套接字信息
    memset(&srv_addr,0,sizeof(srv_addr));
    srv_addr.sin_family = AF_INET;
    srv_addr.sin_addr.s_addr = inet_addr(argv[1]);
    srv_addr.sin_port = htons(port);

    //连接指定的服务器
    ret = connect(connect_fd,(struct sockaddr *)&srv_addr,sizeof(srv_addr));
    if(ret == -1){
        perror("cannot connect to the server");
        close(connect_fd);
           return -1;
    }

    memset(snd_buf,0,1024);

    /*
        用户输入信息后,程序将输入的信息通过套接字发送给服务器,
        然后调用read函数从服务器中读取发送来的信息
        当输入"@"时,程序退出
    */
    while(1){
        write(STDOUT_FILENO,"input message:", 14);
        len = read(STDIN_FILENO,snd_buf,1024);
        if(len > 0)
            write(connect_fd,snd_buf,len);

        len = read(connect_fd,snd_buf,len);
        if(len > 0)
            printf("Message form server: %s\n",snd_buf);
        if(snd_buf[0] == '@')
            break;
    }
    close(connect_fd);
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
设计: 1. 客户端:用户可以通过客户端连接到聊天程序的服务器,与其他用户进行实时聊天。客户端需要支持用户注册、登录、发送消息和接收消息等功能。 2. 服务器:服务器是聊天程序的核心,它负责接收和转发用户的消息,维护用户的在线状态和身份验证等任务。服务器需要支持多个客户端连接,使用数据库存储用户信息。 实现: 1. 服务器端: (1)搭建服务器环境,开启TCP服务端口并监听客户端连接请求。 (2)设计数据库,存储用户信息,包括用户名、密码和在线状态等。 (3)实现用户注册功能:用户可以输入用户名和密码注册账号,服务器需要验证并将用户信息保存到数据库中。 (4)实现用户登录功能:用户可以输入用户名和密码登录聊天程序,服务器需要验证用户的身份并将用户标记为在线状态。 (5)实现消息转发功能:服务器接收客户端发送的消息并将其转发给其他在线用户。 (6)实现用户下线功能:用户可以选择退出聊天程序,服务器需要将用户标记为下线状态并关闭与该用户的连接。 2. 客户端: (1)实现用户注册和登录功能:用户需要输入用户名和密码才能注册和登录聊天程序。 (2)实现发送消息功能:用户可以输入消息并发送给其他在线用户。 (3)实现接收消息功能:用户可以接收其他在线用户发送的消息。 (4)实现用户下线功能:用户可以选择退出聊天程序。 注意事项: 1. 数据库需要进行备份和恢复,以防数据丢失。 2. 用户身份验证需要使用加密算法保证安全性。 3. 系统需要进行安全性测试和漏洞扫描,以确保系统安全性。 4. 聊天程序需要考虑用户数量、消息传输速度等因素,需要进行优化和测试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值