TCP协议----客户端与客户端之间通信

本文介绍了一个简易聊天服务器的实现过程,包括服务器端和客户端的代码示例。该服务器使用多线程处理多个客户端的连接请求,并能实现客户端间的基本消息收发功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

服务器

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

#define PORT 123

struct info     //定义结构体用于存放套接字的描述符,以及来自客户端发送的消息内容
{
    int num;
    char buf[100];
};

void *Recv(void *arg)
{
    pthread_detach(pthread_self());   //线程分离,确保资源的释放

    struct info Buff;
    int ret;

    while(1)
    {
        ret = recv(*(int *)arg,&Buff,sizeof(Buff),0);  //接收客户端的消息
        if(-1 == ret)
        {
            perror("recv");
            exit(1);
        }
        if(!strcmp(Buff.buf,"bye"))
        {
            close(*(int *)arg);
            break;
        }

        printf("Recv form client %d : %s\n",*(int *)arg,Buff.buf);


        ret = send(Buff.num,&Buff,sizeof(Buff),0);  //将消息发送给客户端
        if(-1 == ret)
        {
            perror("send");
            exit(1);
        }

        memset(&Buff,0,sizeof(Buff));
    }

}


int main()
{
    int sockfd,ret,fd[100] = {0};
    pthread_t tid[100] = {0};
    int i = 0;
    int length;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;

    printf("Start ....\n");
    sockfd = socket(PF_INET,SOCK_STREAM,0);   //创建socket
    if(-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }

    int opt = 1;
    setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

    memset(&server_addr,0,sizeof(server_addr));
    server_addr.sin_family = PF_INET;
    server_addr.sin_port = PORT;
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    printf("Binding ....\n");
    ret = bind(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr));  //将信息绑定到socket
    if(-1 == ret)
    {
        perror("bind");
        exit(1);
    }

    printf("Listening ...\n");
    ret = listen(sockfd,5);
    if(-1 == ret)
    {
        perror("listen");
        exit(1);
    }

    while(1)
    {
        length = sizeof(client_addr);
        fd[i] = accept(sockfd,(struct sockaddr*)&client_addr,&length);   //接收多个客户端的连接
        if(-1 == fd[i])
        {
            perror("accept");
            exit(1);
        }

        printf("Accept   %d,  Port   %d  \n",fd[i],server_addr.sin_port);

        ret = pthread_create(&tid[i],NULL,Recv,(void *)&fd[i]);  //为每个客户端创建线程,来处理来自每个客户端发送来的信息
        if(ret != 0)
        {
            perror("pthread_create");
            exit(1);
        }

        i++;
    }

    close(sockfd);
    return 0;

}
客户端


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

pthread_t tid[2];
#define PORT 123

struct info
{
    int  num;
    char buf[100];
};

void *my_send(void *arg)
{
    struct info SendBuff = {0};
    int ret,oldtype;

    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&oldtype);

    while(1)
    {
        scanf("%s  %d",SendBuff.buf,&SendBuff.num);

        ret = send(*(int *)arg,&SendBuff,sizeof(SendBuff),0);
        if(-1 == ret)
        {
            perror("send");
            exit(1);
        }
        if(!strcmp(SendBuff.buf,"bye"))
        {
            close(*(int *)arg);
            pthread_cancel(tid[1]);
            break;
        }
        memset(&SendBuff,0,sizeof(SendBuff));
    }

}

void *my_recv(void *arg)
{
    struct info RecvBuff = {0};
    int ret;

    while(1)
    {
        ret = recv(*(int *)arg,&RecvBuff,sizeof(RecvBuff),0);
        if(-1 == ret)
        {
            perror("recv");
            exit(1);
        }
        printf("\t\t %s \n",RecvBuff.buf);
        memset(&RecvBuff,0,sizeof(RecvBuff));
    }

}


int main()
{
    int sockfd,ret;

    struct sockaddr_in server_addr;

    sockfd = socket(PF_INET,SOCK_STREAM,0);
    if(-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }

    memset(&server_addr,0,sizeof(server_addr));
    server_addr.sin_family = PF_INET;
    server_addr.sin_port = PORT;
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    printf("Connecting ...\n");
    ret = connect(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr));
    if(-1 == ret)
    {
        perror("connect");
        exit(1);
    }

    ret = pthread_create(&tid[0],NULL,my_send,(void *)&sockfd);
    if(ret != 0)
    {
        perror("pthread_create");
        exit(1);
    }

    ret = pthread_create(&tid[1],NULL,my_recv,(void *)&sockfd);
    if(ret != 0)
    {
        perror("ptherad_create2");
        exit(1);
    }

    pthread_join(tid[0],NULL);
    pthread_join(tid[1],NULL);

    close(sockfd);

    return 0;
}


执行结果
服务器
    Start ....
    Binding ....
    Listening ...
    Accept   4,  Port   123  
    Accept   5,  Port   123  
    Recv form client 4 : hello
    Recv form client 5 : hello

客户端1
    Connecting ...
    hello 5
                     hello 
    bye

客户端2
    Connecting ...
                     hello 
    hello 4
    bye



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值