MENU

网络聊天程序的设计与实现

December 16, 2019 • 阅读: 3320 • 笔记&折腾



基于Socket通信原理。原理请点击 Socket

目录:

1、添加库

编辑环境为CodeBlocks。首先添加要用的库。

具体操作为:Settings --> Compiler Settings --> Linker settings,然后点击Add,找到路径 E:\CodeBlocks\MinGW\lib\libws2_32.a (根据CB安装的路径不同自行改变),在右侧输入 -lws2_32,点击OK保存,重启CodeBlocks添加成功。

2、代码

Server.cpp

#include <stdio.h>
#include <Winsock2.h>
#pragma comment(lib, "WS2_32")  // 链接到WS2_32.lib
using namespace std;
#include <fstream>
#include <string>
#include <iostream>


DWORD WINAPI RECVm(void *Param){
    char sendBuf[50];//缓冲区
    char recvBuf[50];//缓冲区
    char username[50]={0}; // 用户名

    SOCKET sockConn = *((SOCKET *)Param);

    strcpy(sendBuf,"Join in chatroom success!You can start chatting...\n");
    send(sockConn,sendBuf,strlen(sendBuf)+1,0);//将数据原样返回
    recv(sockConn,recvBuf,50,0);
    strcpy(username,recvBuf);
    printf("%s has join in chatting room.\n",username);
    while(1)
    {
        //接收
        if(recv(sockConn,recvBuf,50,0)<=0){
            printf("%s has exit!\n",username);
            break;
        }
        if(recvBuf!=""){
            printf("%s: %s\n",username,recvBuf);
        }
        strcpy(recvBuf,"");
    }
    closesocket(sockConn);
    //closesocket(sockSrv);
    return 0;
}

int main()
{
    printf("Welcome to chatting room.....\n");
    WORD wVersionRequested;//wVersionRequested 是我们要求使用的 WinSock 的版本。
    WSADATA wsaData;
    int err;
    wVersionRequested = MAKEWORD( 1, 1 );
    err = WSAStartup( wVersionRequested, &wsaData );
    if ( err != 0 ){
        return 0;}
    if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ){
        WSACleanup( );
        return 0;}
    //创建套接字
    SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);
    //创建sockaddr_in结构体变量,绑定套接字
    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//通讯地址
    addrSrv.sin_family=AF_INET; //sin_family必须为AF_INET,ipv4
    addrSrv.sin_port=htons(6000); //端口号
    //将套接字和 IP,端口 绑定
    bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
    //进入监听状态,后台等待连接队列的最小限制值5
    listen(sockSrv,5);
    //接收
    SOCKADDR_IN addrClient;
    int len=sizeof(SOCKADDR);
    while(1){
        SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);
        CreateThread(NULL,0,RECVm,&sockConn,0,NULL);
    }
}

Client.cpp

#include <iostream>
#include <stdio.h>
#include <Winsock2.h>
#pragma comment(lib, "WS2_32")
using namespace std;
//
int main()
{
    //初始化
    WORD wVersionRequested; //版本
    WSADATA wsaData;
    int err;
    wVersionRequested = MAKEWORD( 1, 1 ); //主版号为1,副版号为1
    err = WSAStartup( wVersionRequested, &wsaData );
    if ( err != 0 )
    {
        return 0;
    }
    if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )
    {
        WSACleanup( );
        return 0;
    }
    //创建套接字
    SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);

    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
    addrSrv.sin_family=AF_INET;
    addrSrv.sin_port=htons(6000);
    //创建连接
    connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
    //发送
    char yourname[50]={0};
    printf("Please enter your username: ");
    gets(yourname);
    send(sockClient,yourname,strlen(yourname)+1,0);

    char recvBuf[50];
    recv(sockClient,recvBuf,50,0);
    printf("Response: %s\n",recvBuf);
    while(1){
        printf("Enter Messages: ");
        gets(yourname);
        send(sockClient,yourname,strlen(yourname)+1,0);
        //recv(sockClient,recvBuf,50,0);
        //printf("Response: %s\n",recvBuf);
    }
    //char recvBuf[50];
    //recv(sockClient,recvBuf,50,0);
    //printf("Response: %s\n",recvBuf);
    closesocket(sockClient);
    WSACleanup();
}

3、运行程序

先运行Server程序,然后再运行Client程序,可运行多个Client程序,即一个服务端,多个客户端。

效果图:

Last Modified: February 6, 2021
Leave a Comment

4 Comments
  1. wang wang

    我来评论一下
    首先客户端退出后没做判断导致服务端死循环
    第二客户端没做接收消息处理
    第三无用代码写太多

    1. starMan starMan

      @wang你说的没错,我会找时间修改的?

    2. starMan starMan

      @starMan客户端的BUG已经修改

  2. Ashen one Ashen one

    test