寒假学习(9)(C语言9+模数电9)

写了一个聊天室,可以支持多人在线,但是现在的问题是发送信息存在无法覆盖的问题

第一个是服务端的代码,第二个是客户端的代码

cpp 复制代码
//聊天室
//服务端流程
//1 创建socket套接字:网络接口

//2 绑定IP和端口号;IP是电脑的地址,端口号是APP的地址

//3 监听:只是用来接收连接的

//4 接收客户端连接

//5 接收客户端消息

//6 发送消息给客户端

//7 关闭套接字

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")

//客户端线程函数
DWORD WINAPI client_thread(LPVOID lpParameter);


int main ()
{
    //在windos上开启网络权限
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    //非常固定,只有windos需要

    //创建套接字
    /*
    SOCKET socket(int af, int type, int protocol);
    af: 地址族,AF_INET表示IPv4 // AF_INET6表示IPv6
    type: 套接字类型,SOCK_STREAM表示TCP//一个是流式协议,一个是数据包
    protocol: 协议,0表示使用默认协议
    */

    SOCKET listen_socket = socket(AF_INET, SOCK_STREAM, 0);

    //判读是否创建成功
    if (listen_socket == INVALID_SOCKET)
    {
        printf("socket failed: %d,no creat\n", WSAGetLastError());
        return 1;
    }

    //绑定IP和端口号

   

    struct sockaddr_in server_addr;

    server_addr.sin_family = AF_INET;

    server_addr.sin_port = htons(8080);
    //这里涉及到大小端问题,htons(8080)表示将8080转换为网络字节序

    //server_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//可以理解为一个选项 网卡 127.0.0.1(本地回环)  只接受那个网卡的数据
    long ip = inet_addr("0.0.0.0");
    server_addr.sin_addr.S_un.S_addr = ip;

    //sockaddr_in的成员是
    //unsigned short sin_family;
    //unsigned short sin_port;
    //struct in_addr sin_addr;  
    //sin_family: 地址族,AF_INET表示IPv4
    //sin_port: 端口号,htons(8080)表示将8080转换为网络字节序
    //sin_addr.S_un.S_addr: IP地址,INADDR_ANY表示任何IP地址

     /*

    int bind(SOCKET s, const struct sockaddr *addr, int addrlen);

    s: 套接字

    addr: 地址结构体

    addrlen: 地址结构体长度

    */

    //sockaddr也是一个结构体,但是它是通用的,可以用于任何协议实际上和sockaddr_in是一样的

    int ret = bind(listen_socket, (struct sockaddr *)&server_addr, sizeof(server_addr));

    //判断是否绑定成功

    if (ret == SOCKET_ERROR)

    {

        printf("bind failed: %d,no bind\n", WSAGetLastError());

        return 1;

    }

    //3.开启监听属性

    //需要用到listen函数
    //listen函数的参数是
    //套接字和最大连接数
    //最大连接数是指服务器可以同时处理的最大连接数
    //如果服务器的连接数超过了最大连接数,那么新的连接将被拒绝

    //判断是否开启成功
    if (listen(listen_socket, 10) == SOCKET_ERROR)
    {
        printf("listen failed: %d\n", WSAGetLastError());
        closesocket(listen_socket);
        WSACleanup();
        return 1;
    }

    //等待客户端连接
    //accept函数用于接受客户端连接
    //accept函数的参数是
    //套接字
    //客户端地址结构体
    //地址结构体长度
    //这是一个阻塞函数,等到客户端连接后才返回,如果没有客户端连接,则一直等待
    SOCKET client_socket;
    struct sockaddr_in client_addr;
    int client_addr_len = sizeof(client_addr);

    while(1)
    {
        client_socket = accept(listen_socket, (struct sockaddr *)&client_addr, &client_addr_len);
        //返回的SOCKET是客户端的套接字,才是和客户端通信的套接字

        //判断是否连接成功
        if (client_socket == INVALID_SOCKET)
        {
            printf("accept failed: %d\n", WSAGetLastError());
            continue;
        }

        SOCKET *sockfd = (SOCKET *)malloc(sizeof(SOCKET));
        *sockfd = client_socket;

        //创建线程处理客户端连接
        HANDLE hThread = CreateThread(NULL, 0, client_thread, sockfd, 0, NULL);
        if (hThread == NULL)
        {
            printf("CreateThread failed\n");
            free(sockfd);
            closesocket(client_socket);
        }
        else
        {
            CloseHandle(hThread);
        }

        printf("Client connected!\n");
    }

    closesocket(listen_socket);
    WSACleanup();

    return 0;
}

DWORD WINAPI client_thread(LPVOID lpParameter)
{
    SOCKET *sockfd = (SOCKET *)lpParameter;
    SOCKET client_socket = *sockfd;
    free(sockfd);

    char buf[1024] = {0};

    while(1)
    {
        int recv_ret = recv(client_socket, buf, sizeof(buf), 0);

        if (recv_ret == SOCKET_ERROR)
        {
            printf("recv failed: %d\n", WSAGetLastError());
            break;
        }
        else if (recv_ret == 0)
        {
            printf("Client disconnected\n");
            break;
        }

        printf("recv: %s\n", buf);

        send(client_socket, buf, recv_ret, 0);
    }

    closesocket(client_socket);

    return 0;
}
cpp 复制代码
//聊天室的客户端
//创建socket套接字
//连接服务器
//发送消息
//接收消息
//关闭套接字(连接)
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")

int main()
{
    // 初始化Winsock
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        printf("Failed to initialize Winsock\n");
        return 1;
    }

    // 创建套接字

    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);

    if (sock == INVALID_SOCKET) {

        printf("Failed to create socket\n");

        WSACleanup();

        return 1;

    }

    //连接服务器
    struct sockaddr_in target;
    target.sin_family = AF_INET;
    target.sin_port = htons(8080);
    target.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

    if (connect(sock, (struct sockaddr*)&target, sizeof(target)) == SOCKET_ERROR) {
        printf("Failed to connect to server\n");
        closesocket(sock);
        WSACleanup();
        return 1;
    }

    while(1)
    {
    //发送信息
    char buffer[1024];
    printf("请输入要发送的信息:");
    scanf("%s", buffer);
    send(sock, buffer, strlen(buffer), 0);

    // 接收服务器响应
    memset(buffer, 0, sizeof(buffer));
    int ret = recv(sock, buffer, sizeof(buffer) - 1, 0);
    printf("收到服务器响应:%s\n", buffer);
    if(ret<=0)break;
    }

    // 关闭套接字和清理Winsock
    closesocket(sock);
    WSACleanup();

    return 0;
}   
相关推荐
微小冷5 小时前
Rust异步编程详解
开发语言·rust·async·await·异步编程·tokio
CappuccinoRose5 小时前
JavaScript 学习文档(二)
前端·javascript·学习·数据类型·运算符·箭头函数·变量声明
A9better5 小时前
C++——不一样的I/O工具与名称空间
开发语言·c++·学习
清水白石0085 小时前
《为什么说 deque 是 Python 滑动窗口的“隐藏神器”?深入解析双端队列的高效之道》
开发语言·python
杜子不疼.5 小时前
Ascend_C自定义算子开发
c语言·开发语言
小乔的编程内容分享站5 小时前
C语言笔记之函数
c语言·笔记
AI职业加油站5 小时前
职业提升之路:我的大数据分析师学习与备考分享
大数据·人工智能·经验分享·学习·职场和发展·数据分析
WooaiJava5 小时前
流式TTS音频播放项目 - 面试问答(后端)
java·开发语言
新缸中之脑5 小时前
开发AI代理必备的8个Python 库
开发语言·人工智能·python
暴走十八步5 小时前
PHP+vscode开启调试debug
开发语言·vscode·php