参考

传送门 - 1 - csdn - 2112222222222
传送门 - 2 - bilibili - 憧憬少
传送门 - 3 -

要求

  1. 开发一个聊天程序
  2. 包含客户端和服务器段
  3. 编程语言不限
  4. 要能在两台PC机上运行

如何实现

通过 socket 实现 两台pc之间的聊天

什么是socket

  • Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。
  • 在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

socket 是如何连接的

  1. 服务器端先初始化Socket
  2. 然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。
  3. 在这时如果有个客户端初始化一个Socket,然后连接服务器(connect)
  4. 如果连接成功,这时客户端与服务器端的连接就建立了
  5. 客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据
  6. 最后关闭连接,一次交互结束。

参考文档:传送门

实现环境

  1. Visual Studio 2013
  2. windows 7 (机房电脑)

相关问题解决

解决 mircsoft visual studio 2013 无法打开 winsock2.h 头文件

  1. 确保
#pragma comment (lib, "ws2_32.lib") // 链接ws2_32.lib文件

该语句放置在前面,首先链接ws2_32.lib文件

  1. 打开 项目

    选择 项目属性
    配置属性调整平台工具集为XP那一项

    记得点击应用,然后确定

解决无法打开 “stdafx.h” 文件的问题

microsoft visual studio 2013版本已经提前帮助项目预编译该文件了,所以不需要include

编译运行产生方法不安全提示时解决办法


server于client都将SDL检查设置为否

结果代码

服务器端代码

//server
#pragma comment(linker, "/STACK:36777216")
//#pragma GCC optimize ("O2")
/**
*    This code has been written by YueGuang, feel free to ask me question. Blog: http://www.moonl1ght.xyz
*    created:
*/
#define LOCAL
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>//#include <tr1/unordered_set>
//#include <tr1/unordered_map>
//#include <array>using namespace std;// un template header#pragma comment (lib, "ws2_32.lib") // 链接ws2_32.lib文件
#include <Winsock2.h> //windows socket编程头文件//自定义头文件//}/* .................................................................................................................................. *//*
bug 说明区域
1.颜色设置setcolor还不能使用
*//*
变量解释说明区域 QAQ
*/// 全局常量
const int BUF_SIZE = 2048;
const int SEND_SIZE = 1000;
const int MAX_BUF_SIZE = 500;
const int NICKNAME_LEN = 20;
const int MAX_CLIENT_COUNT = 20;// 全局变量
SOCKET sockSer, sockCli;
SOCKADDR_IN addrSer, addrCli;// address 地址  客户端地址和服务器地址
SOCKET NewConnection; //用于接受来自客户端的链接int clientCount = 0;
int naddr = sizeof(SOCKADDR_IN);
int Ret;
char sendbuf[BUF_SIZE];
char inputbuf[BUF_SIZE];
char recvbuf[BUF_SIZE];//该结构体的目的是允许多台PC机对服务器进行访问//全局函数using namespace std;int main(){//\第一步,加载socket函数,载入socket库WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){//setColor(COLOR_ERROR);cout << "呐呐呐,载入socket库失败!" << '\n';system("pause");return 0;}//\第二步,创建一个监听套接字sockser, 创建socket(地址描述(AF_INET格式 - ipv4),指定socket类型(使用的是流式套接字即TCP协议), 指定协议if ((sockSer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET){printf("当前为无效套接,程序结束");system("pause");return 0;}//\第三步,初始化服务器的地址包,填写相关信息/**  1.AF_INET优先赋值,这是由于该值是告诉winsock我们使用的是ip地址簇*   2.填写用来通讯的ip地址*  3.填写端口号**/char ip[] = "192.168.81.90";cout << "呐呐呐,本地IP是" << ip << "该电脑已经开启!\n";addrSer.sin_family = AF_INET;addrSer.sin_port = htons(5000);addrSer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//\第四步,将创建的sockser套接字和上面填写的相关地址信息绑定在一起,bind函数有很多,我们要选择的是sock中的所以加头文件的时候要注意不要多加if (bind((SOCKET)sockSer, (SOCKADDR *)&addrSer, sizeof(addrSer)) == SOCKET_ERROR){printf("BIND_ERROR: %d\n", SOCKET_ERROR);return 0;}cout << "二次元世界连接成功!" << endl;//\第五步,让服务器Socket开启监听,并且设置最大的等待连接数,等待连接数(半连接)过大会给服务器造成负载if (listen(sockSer, 5) == SOCKET_ERROR){printf("LISTEN_ERROR: %d\n", SOCKET_ERROR);system("pause");return 0;}//\第六步,客户端连接到达时,本服务器需接受连接,注意接受链接用的是客户端的变量即Cliint ClientAddrLen = sizeof(addrCli);printf("正在接受连接...");if ((NewConnection = accept(sockSer, (SOCKADDR *)&addrCli, &ClientAddrLen)) == INVALID_SOCKET){printf("ACCPET_ERROR: %d\n", INVALID_SOCKET);closesocket(sockSer);return 0;}printf("检测到一个来自三次元的连接: %s 端口:%d\n", inet_ntoa(addrCli.sin_addr), ntohs(addrCli.sin_port));//\第七步,开始接听,true情况下进程不关闭就不会结束,但需要考虑电脑while (true){//接收数据Ret = recv(NewConnection, recvbuf, BUF_SIZE, 0);if (Ret > 0)printf("JOJO对你说: %s\n", recvbuf);else if (Ret < 0)printf("RECV_ERROR: %d\n", SOCKET_ERROR);else{printf("对方觉得二次元浓度过高,退出了聊天!");break;}//发送数据printf("\n说:");scanf("%s", sendbuf);if (strcmp(sendbuf, "quit") == 0)   //退出break;if (send(NewConnection, sendbuf, BUF_SIZE, 0) == SOCKET_ERROR){printf("消息发送失败!\n");break;}}//关闭连接shutdown(NewConnection, SD_BOTH);closesocket(NewConnection);//关闭socket库closesocket(sockSer);//清空加载项if (WSACleanup() == SOCKET_ERROR){printf("WSACLEANUP_ERROR: %d\n", WSAGetLastError());return 0;}system("pause");return 0;
}

客户端代码

#pragma comment(linker, "/STACK:36777216")
//client
//client
#pragma comment(linker, "/STACK:36777216")
//#pragma GCC optimize ("O2")
/**
*    This code has been written by YueGuang, feel free to ask me question. Blog: http://www.moonl1ght.xyz
*    created:
*/#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>//#include <tr1/unordered_set>
//#include <tr1/unordered_map>
//#include <array>using namespace std;// un template header#pragma comment (lib, "ws2_32.lib") // 链接ws2_32.lib文件
#include <Winsock2.h> //windows socket编程头文件/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*///全局常量
const int BUF_SIZE = 2048;
const int SEND_SIZE = 1000;
const int MAX_BUF_SIZE = 200;//全局变量
SOCKET sockSer, sockCli;
SOCKADDR_IN addrSer, addrCli;// address 地址  客户端地址和服务器地址
int naddr = sizeof(SOCKADDR_IN);
char sendbuf[BUF_SIZE];
char inputbuf[BUF_SIZE];
char recvbuf[BUF_SIZE];
int Ret;//全局函数
// 接收线程的设置是死循环不断得提交recv申请,如果有反馈,就输出。
DWORD WINAPI Client_Receive_Thread(LPVOID lp) {SOCKET *s = (SOCKET*)lp;int nrecv;while (true){// 监听服务器端消息char recvBuf[SEND_SIZE]; //注意使用的是 B// recv 的第一个参数是当前socketint res = recv(sockCli, recvBuf, SEND_SIZE, 0); // 最后参数设置成0,表示非阻塞if (res > 0) // 由于socket默认的阻塞,因此recv会自动阻塞{printf("%s\n", recvBuf);}}
}int main(){//\加载socket函数,载入socket库WSADATA WSAData;if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0){//setColor(COLOR_ERROR);cout << "呐呐呐,载入socket库失败!" << '\n';system("pause");return 0;}char ip[] = "192.168.81.90";cout << "呐呐呐,本地IP是" << ip << "该电脑已经开启!\n";//setColor(COLOR_NORMAL);//初始化服务器地址addrSer.sin_family = AF_INET;addrSer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");addrSer.sin_port = htons(5000);//创建socket(地址描述(AF_INET格式 - ipv4),指定socket类型(使用的是流式套接字即TCP协议), 指定协议sockSer = socket(AF_INET, SOCK_STREAM, 0);//建立连接if (connect(sockSer, (SOCKADDR *)&addrSer, sizeof(SOCKADDR)) == SOCKET_ERROR){cout << "CONNECT_ERROR : " << SOCKET_ERROR << endl;return 0;}else{cout << "二次元世界,连接成功!" << endl;}//读取用户名char username[50];printf("请输入您的用户名: ");scanf("%s", username);const int max_connet_cnt = 20; //最大尝试连接次数int cnt = 0;while (true){//发送数据cout << '\n' << username << "说:";cin >> sendbuf;if (strcmp(sendbuf, "quit") == 0){break;}if (send(sockSer, sendbuf, BUF_SIZE, 0) == SOCKET_ERROR){cout << "消息发送失败" << endl;break;}//接收数据Ret = recv(sockSer, recvbuf, BUF_SIZE, 0);if (Ret < 0){cout << "RECV_ERROR" << SOCKET_ERROR << endl;break;}else if (Ret == 0){cout << "对方退出聊天程序,聊天结束" << endl;break;}else{cout << "Server对你说:" << recvbuf << endl;}}//关闭socket库closesocket(sockSer);closesocket(sockCli);WSACleanup(); //清空加载项return 0;
}

运行截图1

获取本地IP的函数

void getLocalIP(char localIp[], int n){gethostname(localIp, n);HOSTENT *host = gethostbyname(localIp);in_addr PcAddr;int i = 0;while (true){char * p = host->h_addr_list[i];if (p == NULL){break;}memcpy(&(PcAddr, S_un.S_addr), p, host->h_length);strcpy(localIp, inet_ntoa(PcAddr));}
}

【计算机网络】大作业-实现两台pc间交流的简单的聊天软件相关推荐

  1. 串口通信--两台PC机之间的简单传输

    串口通信–两台PC机之间的简单传输 文章目录 串口通信--两台PC机之间的简单传输 1.实验器材 2.实物连接 3.选择文件发送 4.计算比较 5.总结 1.实验器材 两台 PC 机器 两个 usb ...

  2. 两台pc如何高速度传输大文件

    今天笔记本跑一个大一点的项目,8G的内存直接100%,i5的CPU直接75%并且在超频工作了,原本1.6Ghz的频率直接飙到了3.8Ghz,由于项目性质原因,采用的是公司配的笔记本,但是年初采购的联想 ...

  3. 苏州科技计算机网络,苏州科技学院-计算机网络大作业-某高校校园网设计.doc

    苏州科技学院-计算机网络大作业-某高校校园网设计 PAGE PAGE 9 苏州科技学院 计算机网络大作业 某高校校园网设计 班级: 学号: 姓名: 2011年12月10日 一.需求分析 随着计算机.通 ...

  4. 如何让两台PC通过一根网线相互通信?

    1.如果是同类设备之间相连,比如PC-PC,交换机-交换机,需要用交叉线. 2.如果是不同类设备相连,比如PC-交换机,PC-路由器,需要用直连线. 之前用普通网线(直连线)连接笔记本A和笔记本B,在 ...

  5. 两台PC实现串口通信以及点阵字模读写

    目录 一.pc串口通信 1.连线设置 2.打开调试助手 2.1加载图片 2.2 设置波特率为15200 2.3点击发送文件 3.将波特率设为2000000 4.结果分析 二.点阵汉字读取与打印 1.点 ...

  6. SQL server 两台服务器间连接查询

    --两台服务器间连接查询: --建立连接: sp_addlinkedserver hs sp_addlinkedserver hs1 EXEC sp_addlinkedsrvlogin 'hs', ' ...

  7. 使用NFS 实现两台服务器间的数据备份. -- NFS 设置部分.

    要求:把开发服务器,CRM 服务器中的每天数据备份文件拷贝到另一台备份服务器CRMBAK中. 1.在CRMBAK服务器的设置: 使用ROOT 登录CRMBAK. # ps -aux|grep port ...

  8. 【Linux学习笔记】用nc实现两台主机间的文件传输(不需要输密码)

    通常,可以用scp完成两台主机间的文件传输任务,但在主机间未建立信任关系的情况下,scp每次都需要输入密码,用起来感觉不是很方便,之前这篇笔记介绍过不用输入密码执行脚本或传输文件的方法,但对于一些临时 ...

  9. win7 两台PC网线直连创建家庭组局域网分享文件

    设置局域网 首先用网线连接两台电脑,然后打开其中一台右下角的[网络和共享中心],点击左侧的[更改适配器设置]: 可以看到本地连接被提示为连接到"未识别的网络": 双击此[本地连接] ...

最新文章

  1. 深度学习和目标检测系列教程 15-300:在 Python 中使用 OpenCV 执行 YOLOv3 对象检测
  2. BZOJ4543 POI2014 Hotel加强版 【长链剖分】【DP】*
  3. .net面试题大全,绝大部分面试题
  4. 约束布局constraint-layout导入失败的解决方案 - 转
  5. atlas mysql 安装_atlas中间件安装配置
  6. python内置模块~shutil
  7. 深度理解“CPU内部寻址方式”
  8. 多元统计分析——多元线性回归
  9. 暴雪正在等待另一项_守望先锋更新一直显示正在等待另一项安装或更新怎么办...
  10. Bzoj1208 宠物收养所
  11. 产品经理如何写PRD文档[最全]
  12. srv.exe蠕虫病毒~
  13. 火影段位赛服务器响应超时,火影手游,谜一样的跨服积分赛已上线,奖励不到位惹人嫌弃...
  14. 如何把采集到的数据存入mysql_数据采集教程_数据发布_如何发布到数据库MySQL_后羿采集器...
  15. 【年度总结】2021 邂逅前端,入坑算法
  16. 计算机网络唤醒技术说明与实现
  17. Xcode安装特定版本系统的模拟器(不支持断点下载所以总是下载失败)
  18. starling 笔记
  19. 【C++】斐波那契凤尾
  20. 技术小白用python搭建微信公众号后台

热门文章

  1. 多语言机器翻译 | (2) 编解码器结构
  2. 客户信用风险预测——基于logit模型
  3. 联合证券|再创纪录,外资狂买超1000亿!券商、期货板块持续活跃
  4. 真实案例详述:丢手机太危险了
  5. 80多款的QQ头像PSD源码超级多款式
  6. 主打个性化推荐阅读的摘客,玩的是什么?
  7. ip地址的分类和特殊的网络地址-——计算机网络笔记
  8. zblogPHP新主题“度娘”发布
  9. 小白重装系统教程_小白U盘重装原版win7系统教程
  10. 【Unity3D Shader编程】之六 暗黑城堡篇: 表面着色器(Surface Shader)的写法(一)