基于socket的线上聊天框

聊天框1.0

使用说明:
  1. 要求Linux环境,虚拟机或者WSL均可

  2. 命令行执行 g++ Server.cpp -o Serverg++ Client.cpp -o Client 进行编译

  3. 线程A在命令行执行 ./Server 5005,线程B在命令行执行 ./Client 127.0.0.1 5005

  4. 双端轮流输入对话内容,目前仅支持一人一句不能连续多句

  5. 任一方输入 拜拜 结束通信

服务端工作流程:
  1. 创建socket
  2. 把IP地址和端口绑定到socket上
  3. 设置socket为监听模式
  4. 接受客户端的连接请求
  5. 与客户端重复通信,直到通信结束
  6. 关闭socket,释放资源
客户端工作流程:
  1. 创建socket
  2. 向服务端发起连接请求
  3. 与服务端通信,通信结束后断开连接
  4. 关闭socket,释放资源

C++源码

Server端
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
    
    
    if (argc != 2)
    {
    
    
        printf("请输入端口号!\n\n");
        return -1;
    }

    // 第1步:创建服务端的socket。
    int listenfd;
    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
    
    
        perror("socket");
        return -1;
    }

    // 第2步:把服务端用于通信的地址和端口绑定到socket上。
    struct sockaddr_in servaddr; // 服务端地址信息的数据结构。
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;                // 协议族,在socket编程中只能是AF_INET。
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 使用任意ip地址。
    //servaddr.sin_addr.s_addr = inet_addr("192.168.190.134"); // 使用指定ip地址。
    servaddr.sin_port = htons(atoi(argv[1])); // 指定通信端口。
    if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0)
    {
    
    
        perror("bind");
        close(listenfd);
        return -1;
    }

    // 第3步:把socket设置为监听模式。
    if (listen(listenfd, 5) != 0)
    {
    
    
        perror("listen");
        close(listenfd);
        return -1;
    }

    // 第4步:接受客户端的连接。
    int clientfd;                             // 客户端的socket。
    int socklen = sizeof(struct sockaddr_in); // struct sockaddr_in的大小
    struct sockaddr_in clientaddr;            // 客户端的地址信息。
    clientfd = accept(listenfd, (struct sockaddr *)&clientaddr, (socklen_t *)&socklen);
    printf("客户端(%s)已连接。\n", inet_ntoa(clientaddr.sin_addr));

    // 第5步:与客户端通信,接收客户端发过来的报文后,回复ok。
    char buffer[1024];
    int iret;
    while (1)
    {
    
    
        memset(buffer, 0, sizeof(buffer));
        if ((iret = recv(clientfd, buffer, sizeof(buffer), 0)) <= 0) // 接收客户端的请求报文。
        {
    
        
            printf("没收到这条信息!\n");
        }
        else
        {
    
    
            printf("对方:%s\n", buffer);
        }

        if (!strcmp(buffer, "拜拜"))
        {
    
    
            printf("\n结束与对方通信!\n");
            break;
        }

        memset(buffer, 0, sizeof(buffer));
        printf("我:");
        scanf("%[^\n]", buffer);
        char c = getchar();
        if ((iret = send(clientfd, buffer, strlen(buffer), 0)) <= 0) // 向客户端发送响应结果。
        {
    
    
            printf("这条信息没发出去!\n");
        }

        if (!strcmp(buffer, "拜拜"))
        {
    
    
            printf("\n对方已结束通信!\n");
            break;
        }
    }

    // 第6步:关闭socket,释放资源。
    close(listenfd);
    close(clientfd);
}
Client端
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
    
    
    if (argc != 3)
    {
    
    
        printf("请输入ip地址和端口!\n\n");
        return -1;
    }

    // 第1步:创建客户端的socket。
    int sockfd;
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
    
    
        perror("socket");
        return -1;
    }

    // 第2步:向服务器发起连接请求。
    struct hostent *h;
    if ((h = gethostbyname(argv[1])) == 0) // 指定服务端的ip地址。
    {
    
    
        printf("gethostbyname failed.\n");
        close(sockfd);
        return -1;
    }
    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(atoi(argv[2])); // 指定服务端的通信端口。
    memcpy(&servaddr.sin_addr, h->h_addr, h->h_length);
    if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) // 向服务端发起连接清求。
    {
    
    
        perror("connect");
        close(sockfd);
        return -1;
    }

    // 第3步:与服务端通信,发送一个报文后等待回复,然后再发下一个报文。
    char buffer[1024];
    int iret;
    while (1)
    {
    
    
        memset(buffer, 0, sizeof(buffer));
        printf("我:");
        scanf("%[^\n]", buffer);
        char c = getchar();
        if ((iret = send(sockfd, buffer, strlen(buffer), 0)) <= 0) // 向服务端发送请求报文。
        {
    
    
            printf("\n发送失败,通信结束!\n");
            break;
        }

        if (!strcmp(buffer, "拜拜"))
        {
    
    
            printf("\n结束与对方通信!\n");
            break;
        }

        memset(buffer, 0, sizeof(buffer));
        if ((iret = recv(sockfd, buffer, sizeof(buffer), 0)) <= 0) // 接收服务端的回应报文。
        {
    
    
            printf("\n接收失败,通信结束\n");
            break;
        }
        printf("对方:%s\n", buffer);

        if (!strcmp(buffer, "拜拜"))
        {
    
    
            printf("\n对方已结束通信!\n");
            break;
        }
    }

    // 第4步:关闭socket,释放资源。
    close(sockfd);
}
效果演示:
Server端

image-20210827084401226

Client端

image-20210827084332684
 
有关socket可以查看Socket进程通信

猜你喜欢

转载自blog.csdn.net/qq_45753394/article/details/119945128