C++在线多人聊天室

基于SOCKET套接字的聊天程序

当初没有考虑要和别人一起开发什么,所以没有注释,
我还是很相信自己码风的,你肯定看得懂
虽然努力了但还是BUG多多,仅供参考,下次更新就是在暑假了
窝还是一个可怜的高中OIer就不要在意那么多细节嘛QAQ

嗯?问我怎么编译不了?自己百度去啊,怎么用SOCKET,要调哪些编译参数.
这程序可以在局域网里跑,你有钱也可以买个服务器,在服务器上跑(那你就可以在任何有网的地方聊天了 (还不如QQ) )

记住服务端的IP设置是自己的内网IP,而客户端IP设置是服务器的映射IP,当然如果是局域网就不存在这个问题,直接都用内网IP就好.

服务端(cmd界面)


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#pragma comment (lib,"ws2_32.lib")
#define STR_MAX_LEN 200
#define NAME_LEN        15
#define SEND_LEN        STR_MAX_LEN + NAME_LEN + 2

using namespace std;

const int   MAX_ONLINE   =  20;
const char  Server_IP[]  =  "127.0.0.1",//改成你服务器的内网地址!!!!!
                Warn_Buf[]   =  "It's over Max connect!";
list < SOCKET > online;
bool            online_using =  0;

void Wrong_exit(const char* Error_place, int _Code) {
    printf("%s wrong!(at: %d)\n", Error_place, _Code);
    system("pause");
    exit(_Code);
}

void show_time() {
    static char time_l[20], time_n[20];
    static time_t timep;
   {
       time(&timep);
       strftime(time_n, sizeof(time_n), "%Y-%m-%d %H:%M", localtime(&timep));
       if (strcmp(time_l, time_n)) {
           strcpy(time_l, time_n);
           printf("//             %s\n", time_n);
      }
   }
}

void broadcast(const char* name, const char* send_buf) {
    static char ls_send[SEND_LEN];

    strcpy(ls_send, name);
    strcat(ls_send, ": ");
    strcat(ls_send, send_buf);

    while(online_using);
    online_using = 1;

    for(auto i = online.begin();i != online.end();i++)
        send(*i, ls_send, SEND_LEN, 0);

    online_using = 0;
}

void flash_online_num() {
    static char title[100];
    if(online.empty()) strcpy(title, "title=Connect-SAXI-Server");
    else sprintf(title, "title=Connect-SAXI-Server online_now:: %d", online.size());
    system(title);
}

DWORD WINAPI child_thread(LPVOID V_sock) {
    char name       [NAME_LEN];
    char recvbuf    [STR_MAX_LEN];

    SOCKET hsock = (SOCKET) V_sock;
    recv(hsock, name, NAME_LEN, 0);

    show_time();
    printf("%s login Successful!\n", name);
    flash_online_num();
    while(true) {
        recv(hsock, recvbuf, STR_MAX_LEN, 0);
        if(!strcmp(recvbuf, "ord::EXIT")) break;
        broadcast(name, recvbuf);
    }
    online_using = 1;
    online.remove(hsock);
    online_using = 0;

    show_time();
    printf("%s exited!\n", name);
    flash_online_num();
    return 0;
}

void NewHandle(SOCKET &SockFrom) {
    HANDLE  ls_handle;
    DWORD    ls_handle_id;
    ls_handle = (HANDLE)::CreateThread(NULL, 0,
            child_thread, (LPVOID)SockFrom, 0, &ls_handle_id);
}

int main() {
    system("title=Connect-SAXI-Server");
    puts("Connect-SAXI-Server");
    puts("                                        powerd by saxiy");

    WSADATA wsd;
   WSAStartup(MAKEWORD(2, 2), &wsd);
   SOCKET SockServer;
   sockaddr_in ServerAddr, FromAddr;

   ServerAddr.sin_family                =   AF_INET;
   ServerAddr.sin_port                  =   htons(5327);
   ServerAddr.sin_addr.S_un.S_addr  =   inet_addr(Server_IP);

   SockServer = socket(AF_INET, SOCK_STREAM, 0);

   if(bind(SockServer, (sockaddr*)&ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR)
        Wrong_exit("bind", 1);

   if(listen(SockServer, MAX_ONLINE) == SOCKET_ERROR)
    Wrong_exit("listen", 2);

   int Socklen = sizeof(sockaddr);
   while(true) {
        SOCKET SockFrom;
    SockFrom = accept(SockServer, (sockaddr*)&FromAddr, &Socklen);
    if(SockFrom != INVALID_SOCKET) {
            if(online.size() < MAX_ONLINE) {
                while(online_using);
                online_using = 1;
                online.push_back(SockFrom);
                online_using = 0;
                NewHandle(SockFrom);
            } else {
                send(SockFrom, Warn_Buf, int(sizeof(Warn_Buf)/sizeof(char)), 0);
                closesocket(SockFrom);
            }
        }
    }
   WSACleanup();
    return 0;
}

客户端(图形界面)


#include 
#include 
#include 
#include 
#include 
#pragma comment (lib,"ws2_32.lib")
#define W_SIZE          650
#define STR_MAX_LEN 200
#define MEM_STR_LEN 10000
#define IN_TEXT     101
#define OUT_TEXT        201
#define B_DOWN          301

using namespace std;

const char  o_IP[]      =   "127.0.0.1",//改成服务器的映射地址!!!!!
            I_name[]        =   "unnamed";
char    sendbuf[STR_MAX_LEN],
        recvbuf[STR_MAX_LEN],
        memobuf[MEM_STR_LEN];
bool outlock = 0;
SOCKET connection;

void hwndOutput_add_buf(HWND, const char*, bool n = 1);

void show_time(HWND hwndout) {
    static char time_l[20], time_n[20];
    static time_t timep;
    {
        time(&timep);
        strftime(time_n, sizeof(time_n), "%Y-%m-%d %H:%M", localtime(&timep));
        if (strcmp(time_l, time_n)) {
            strcpy(time_l, time_n);
            strcat(memobuf, "//             ");
            strcat(memobuf, time_n);
            strcat(memobuf, "\r\n");
        }
    }
}

SOCKET gotsock(HWND hwndmind) {
    WSADATA wsd;
    WSAStartup(MAKEWORD(2, 2), &wsd);
    SOCKET SockUser;
    sockaddr_in ServerAddr;

    ServerAddr.sin_family               =   AF_INET;
    ServerAddr.sin_port                 =   htons(5327);
    ServerAddr.sin_addr.S_un.S_addr =   inet_addr(o_IP);

    SockUser = socket(AF_INET, SOCK_STREAM, 0);

    if (connect(SockUser, (sockaddr*)&ServerAddr, sizeof(sockaddr)) != SOCKET_ERROR) {
        strcat(memobuf, "//========服务器连接成功========//\r\n");
        hwndOutput_add_buf(hwndmind, "", 0);
        return SockUser;
    } else {
        MessageBox(NULL, "服务器不在线!","Error!", MB_ICONEXCLAMATION | MB_OK);
        exit(0);
    }
}

void w_send(HWND hwndin, HWND hwndlog) {
    GetWindowText(hwndin, sendbuf, STR_MAX_LEN);
    SetWindowText(hwndin, "");

    if(!strcmp(sendbuf, "ord::cls")) {
        strcpy(memobuf, "//==========已清理内存==========//");
        hwndOutput_add_buf(hwndlog, "");
        return;
    }

    //add your new orders here

    send(connection, sendbuf, STR_MAX_LEN, 0);
    if(!strcmp(sendbuf, "ord::EXIT")) exit(0);
}

DWORD WINAPI w_recv(LPVOID hwndout) {
    HWND hwndOut = (HWND) hwndout;
    int noxtime = 0;
    while(noxtime < 3) {
        recv(connection, recvbuf, STR_MAX_LEN, 0);
        if(*recvbuf) {
            noxtime = 0;
            hwndOutput_add_buf(hwndOut, recvbuf);
        } else noxtime++;
        *recvbuf = '\0';
    }
    hwndOutput_add_buf(hwndOut, "//=!服务器已下线,3秒后退出程序!=//");
    Sleep(3000); exit(0);
}

void hwndOutput_add_buf(HWND hwnd, const char* buf, bool n) {
    static int len;

    while(outlock);
    outlock = 1;

    len = strlen(memobuf);
    if(len > MEM_STR_LEN - 500) strcpy(memobuf, "//=========自动清理内存=========//");
    show_time(hwnd);
    if(len > MEM_STR_LEN - 1000) strcpy(memobuf, "//=!即将清理历史;请注意保存数据!=//");

    strcat(memobuf, buf);
    if(n) strcat(memobuf, "\r\n");
    SetWindowText(hwnd, memobuf);
    SendMessage(hwnd, EM_LINESCROLL, 0, Edit_GetLineCount(hwnd));

    outlock = 0;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {

    static HDC              hdc;
    static PAINTSTRUCT  ps;
    static HANDLE           wc_listen;
    static DWORD            wc_listenID = 0;
    static HWND             B_send;
    static HWND             hwndOutput,
                                hwndInput;
    static int              wmID,
                            wmEvent;

    switch(Message) {
        case WM_CREATE: {
            unsigned int std_l = W_SIZE * 0.618 - 83;

            hwndOutput = CreateWindow( TEXT("edit"), NULL,
                                       WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER |
                                       ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
                                       0, 0, W_SIZE - 20, std_l,
                                       hwnd, (HMENU)OUT_TEXT, ((LPCREATESTRUCT) lParam) -> hInstance, NULL );

            hwndInput = CreateWindow( TEXT("edit"), NULL,
                                      WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_BORDER |
                                      ES_LEFT | ES_AUTOHSCROLL,
                                      0, std_l, W_SIZE - 70, 40,
                                      hwnd, (HMENU)IN_TEXT, ((LPCREATESTRUCT) lParam) -> hInstance, NULL );

            HWND B_send=CreateWindow( TEXT("BUTTON"), TEXT("Send"),
                                      WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
                                      W_SIZE - 70, std_l, 50, 40,
                                      hwnd, (HMENU)B_DOWN, (HINSTANCE)GetWindowLong(hwnd, -6), NULL);

            connection = gotsock(hwndOutput);
            send(connection, I_name, int(sizeof(I_name) / sizeof(char)), 0);
            Edit_LimitText(hwndInput, STR_MAX_LEN);
            wc_listen = (HANDLE)::CreateThread(NULL, 0, w_recv, (LPVOID)hwndOutput, 0, &wc_listenID);

            break;
        }
        case WM_PAINT: {
            hdc = BeginPaint(hwnd, &ps);

            //add your paint code here

            EndPaint(hwnd, &ps);
            break;
        }
        case WM_COMMAND: {
            wmID        =   LOWORD(wParam);
            wmEvent =   HIWORD(wParam);
            switch(wmID) {
                case B_DOWN: {
                    w_send(hwndInput, hwndOutput);
                    break;
                }
                //other commands
            }
            break;
        }
        case WM_DESTROY: {
            send(connection, "ord::EXIT", STR_MAX_LEN, 0);
            PostQuitMessage(0);
            break;
        }
        default:
            return DefWindowProc(hwnd, Message, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {

    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    memset(&wc, 0, sizeof(wc));

    wc.cbSize           =   sizeof(WNDCLASSEX);
    wc.lpfnWndProc      =   WndProc;
    wc.hInstance        =   hInstance;
    wc.hCursor          =   LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground    =   (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszClassName    =   "Win_connect";
    wc.hIcon                =   LoadIcon(NULL, IDI_APPLICATION);
    wc.hIconSm          =   LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wc)) {
        MessageBox(NULL, "Window Registration Failed!","Error!", MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "Win_connect", "connect", WS_VISIBLE | WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT,      //     x     //
                          CW_USEDEFAULT,      //     y     //
                          W_SIZE,             //   width   //
                          W_SIZE * 0.618,     //   height  //
                          NULL, NULL, hInstance, NULL);

    if(hwnd == NULL) {
        MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    //Message Rounds
    while(GetMessage(&Msg, NULL, 0, 0) > 0) {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }

    return Msg.wParam;
}
大概就是这么一个玩意儿,有兴趣可以翻我 洛谷的博客 考古去
版权声明:
  • 允许自由转载和使用,但必须保留作者信息及出处

© saxiy 2019.6.11 保留所有权利

你可能感兴趣的:(Windows图形编程,Socket)