寒假学习(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;
}   
相关推荐
豆约翰1 小时前
句子单词统计 Key→Value 动态可视化
开发语言·前端·javascript
好奇龙猫1 小时前
【人工智能学习-AI入试相关题目练习-第十三次】
人工智能·学习
Cult Of1 小时前
一个最小可扩展聊天室系统的设计与实现(Java + Swing + TCP)
java·开发语言·tcp/ip
HeDongDong-2 小时前
详解 Kotlin 的函数
开发语言·python·kotlin
waves浪游2 小时前
Ext系列文件系统
linux·服务器·开发语言·c++·numpy
独自破碎E2 小时前
LCR003-比特位计数
java·开发语言
cq林志炫2 小时前
PHP实现数据动态写入word模板文件里面
开发语言·php
pcm1235672 小时前
设计C/S架构的IM通信软件(2)
java·c语言·架构
2301_817497332 小时前
C++中的适配器模式实战
开发语言·c++·算法