一个简单的网络编程项目
一、 项目的主要功能:
(1)通过客户端与服务端可以进行多人聊天
(2) 客户端和服务端拥有自我检查功能来校检客户端和服务端连接是否成功
(3)客户端可以自定义聊天室内昵称
(4)用户进入聊天室时会有进入时间提醒
(5)用户成功发送文字后有返回成功提
二、 主要技术路线:
通过调用WS2tcpip、winsock2等头文件实现了客户端与服务端之间的信息交流
通过调用time头文件实现了时间显示
这次编写聊天室,本质上是创建socket关键字来实现网络间的通信,更具体的关于我做的客户端的内容,我归结为以下几点:
(1)打开一通信通道,并连接到服务器所在主机的特定端口;
(2)向服务器发服务请求报文,等待并接收应答;继续提出请求......
(3)请求结束后关闭通信通道并终止。
而且理论上来说,服务器进程一般是先启动的。只要系统运行,该服务进程一直存在,直到正常或强迫终止。
大体框架其实在懂了socket编程的思想之后,写起来就很简单,概括起来就是:预留接口,用具体的函数实现功能。
WSAStartup启动对应的版本之后,
用
serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
创建socket,
用
inet_pton(AF_INET, "127.0.0.1", (void*)& addr.sin_addr.S_un.S_addr)
初始化地址,
用
int r = connect(serverSocket, (SOCKADDR*)& addr, sizeof addr)
连接服务器。
其中WSAStartup与WSACleanup对应 ,通过WSACleanup的返回值来确定socket协议是否启动 ;
int r = connect(serverSocket, (SOCKADDR*)& addr, sizeof addr)
其实和TCP/IP协议中三次握手中的第一次握手类似,第一次握手之后,
用
r=send(serverSocket, name, strlen(name), NULL)
进行发送数据,本质上实现起来还是很简单的。
三、 实现的大体框架:
(1) 加载socket库的版本号,进行整体版本的初始化检查
(2)进行请求版本检查
(3)创建socket,定义协议域,类型,协议,并进行检查
(4)初始化地址、端口
(5)绑定socket,把地址端口进行绑定并判断是否成功
(6)对于服务端检查监听是否成功
(7)对于客户端需要判断连接是否成功
(8)进行数据的交互
四、实现代码
#include <iostream> #include<WS2tcpip.h> #include<time.h> #include "winsock2.h" #include "stdlib.h" #include "stdio.h" #include "string" #include<conio.h> #pragma comment (lib, "ws2_32.lib") using namespace std; SOCKET clientSocket[1024]; int k = 0; void communication(LPVOID n)//上传 { char buff[256]; char name[20]; int r; int s; int i = (int)n; int the_name = i; memset(name, 0, 20); s = recv(clientSocket[the_name - 1], name, 19, NULL); while (1) { memset(buff, 0, 256); r = recv(clientSocket[i - 1], buff, 255, NULL); if (r > 0&&s > 0) { cout << name << ":" << buff << endl; for (int j = 0; j < k; j++) { send(clientSocket[j], buff, strlen(buff), NULL); } } } } int main() { char sendBuf[20] = { '\0' }; struct tm t; time_t now; //加载socket库 版本号 WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { cout << "整体版本申请初始化错误" << endl; return -1; } //cout << "整体版本申请初始化成功" << endl; if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { cout << "请求版本失败" << endl; return -1; } //cout << "请求版本成功" << endl; //创建socket SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (serverSocket == INVALID_SOCKET) { cout << "创建socket失败" << endl; return -1; } //cout << "创建socket成功" << endl; SOCKADDR_IN addr = { 0 }; //初始化地址 inet_pton(AF_INET, "127.0.0.1", (void*)& addr.sin_addr.S_un.S_addr); addr.sin_family = AF_INET; addr.sin_port = htons(10001); //绑定Socket int r = bind(serverSocket, (SOCKADDR*)& addr, sizeof(addr)); if (r == -1) { cout << "绑定失败" << endl; return -1; } //cout << "绑定成功" << endl; //listen r = listen(serverSocket, 10); if (r == -1) { cout << "监听失败" << endl; return -1; } //cout << "监听成功" << endl; cout << "###############################################初始化成功,欢迎进入聊天室###############################################" << endl; cout << "制作人:B17040730 B17040731 请启动客户端聊天" << endl; //连接 //地址族 SOCKADDR_IN cAddr = { 0 }; int len = sizeof cAddr; int i = 0; while (i < 1024) { time(&now); localtime_s(&t, &now); clientSocket[i++] = accept(serverSocket, (sockaddr*)& cAddr, &len); k++; if (clientSocket[i - 1] == SOCKET_ERROR) { cout << "错误的客户端" << endl; closesocket(serverSocket); WSACleanup(); return -1; } cout << "########################################################################################################################" << endl; cout << "新的客户端接入 IP地址: " << inet_ntop(AF_INET, (void*)& cAddr.sin_addr, sendBuf, 16) << endl; cout <<"进入时间:"<< t.tm_year + 1900 << "年" << t.tm_mon + 1 << "月" << t.tm_mday << "日" <<t.tm_hour<<"时"<<t.tm_min<<"分"<<t.tm_sec<<"秒" <<endl; cout << "########################################################################################################################" << endl; CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)communication, (LPVOID)i, NULL, NULL); } return 0; }
#include <iostream> #include<WS2tcpip.h> #include "winsock2.h" #include "stdlib.h" #include "stdio.h" #include "string" #pragma comment (lib, "ws2_32.lib") using namespace std; SOCKET serverSocket;//服务器 void recvAndShow() { int r, i = 0; char buff[256]; while (1) { memset(buff, 0, 256); r = recv(serverSocket, buff, 255, NULL); if (r > 0) { i++; } } } int main() { WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { cout << "整体版本申请初始化错误" << endl; } //cout << "整体版本申请初始化成功" << endl; if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { cout << "请求版本失败!\n" << endl; return -1; } //cout << "请求版本成功!\n" << endl; //创建socket serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (serverSocket == INVALID_SOCKET) { cout << "创建socket失败!\n" << endl; return -1; } //cout << "创建socket成功!\n" << endl; //地址族 SOCKADDR_IN addr = { 0 }; //初始化地址 inet_pton(AF_INET, "127.0.0.1", (void*)& addr.sin_addr.S_un.S_addr); addr.sin_family = AF_INET; addr.sin_port = htons(10001); //连接到服务器 int r = connect(serverSocket, (SOCKADDR*)& addr, sizeof addr); if (r == -1) { cout << "连接服务器失败!\n" << endl; return -1; } cout << "###################################################连接服务器成功#######################################################" << endl; CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)recvAndShow, NULL, NULL, NULL); char name[20]; cout << "请输入您的聊天室用户名:" << endl; cin >> name; r = send(serverSocket, name, strlen(name), NULL); if (r > 0) { cout << "########################################################################################################################" << endl; cout << "成功" << endl; } char buff[256]; while (1) { memset(buff, 0, 256); cout << "########################################################################################################################" << endl; cout << "请输入您想输入的内容:" << endl; cin >> buff; r = send(serverSocket, buff, strlen(buff), NULL); if (r < 0) { cout << "########################################################################################################################" << endl; cout <<"发送失败" << endl; cout << "########################################################################################################################" << endl; } } return 0; }