客户端的程序结构前半部分与服务器端基本相同,后半部分也相对简单。相关函数的解释可以参考前文服务器端的内容。有关客户端的内容除个别地方外,就不再做长篇大论的解释。强调一点,如果将此程序移到其它电脑上运行,编译需要release模式,具体做法可以参考上一篇。
客户端程序简介如下:
一、头文件部分
#include<iostream>
using namespace std;
#include<thread>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
#pragma warning (disable: 4996) //解决C4996报错问题
二、声明函数及全局变量
void clientRecv();
void clientSend();
SOCKET pubServerSock; //服务器端SOCKET对象(客户端需与服务器端联系)
三、主函数编写(客户端与服务器端链接的具体步骤)
int main(void)
{
步骤1. 窗口设置
system("color 1A");
system("title Client Station");
system("mode con cols=60 lines=30");
步骤2. 打开网络库
WORD wdVersion = MAKEWORD(2, 2);
WSADATA wdSockMsg;
int nRes = WSAStartup(wdVersion, &wdSockMsg);
if (0 != nRes)
{
cout << "网络库打开过程失败,程序即将结束!" << endl;
system("pause");
return 0;
}
步骤3. 检验网络库版本号
if (2 != HIBYTE(wdSockMsg.wVersion) || 2 != LOBYTE(wdSockMsg.wVersion))
{
cout << "网络库版本有误,程序即将结束!" << endl;
system("pause");
WSACleanup();
return 0;
}
步骤4. 创建服务器端SOCKET对象(便于客户端联系服务器)
pubServerSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == pubServerSock)
{
cout << "创建服务器端SOCKET对象失败,程序即将结束!" << endl;
system("pause");
WSACleanup();
return 0;//结束程序运行
}
printf("已与服务器连接...\n");
步骤5. 链接到服务器(关于IP地址:客户端填写IP地址等也是服务器端的,注意事项参考前文
sockaddr_in serverSockAdd;
serverSockAdd.sin_family = AF_INET;
serverSockAdd.sin_port = htons(12345); //端口号与服务器程序保持一致
serverSockAdd.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//同上
int res = connect(pubServerSock, (struct sockaddr*)&serverSockAdd, sizeof(serverSockAdd));
if(SOCKET_ERROR == res)
{
cout << "链接服务器失败,程序即将结束!" << endl;
system("pause");
closesocket(pubServerSock);
WSACleanup();
return 0;
}
步骤6. 与服务器接收、发送消息。
thread clientThread1(clientRecv); //利用多线程类调用子程序
thread clientThread2(clientSend); //利用多线程类调用子程序
clientThread1.join();
clientThread2.join();
步骤7. 程序结束
closesocket(pubServerSock);
WSACleanup();
system("pause");
return 0;
}
四、子程序实现
1. 收信息子程序
void clientRecv()
{
while (true)
{
char buf[1024] = { 0 };
int res = recv(pubServerSock, buf, 1024 - 1, 0);
if (SOCKET_ERROR == res || 0 == res)
{
cout << "程序运行失败或链接中断!" << endl;
closesocket(pubServerSock);
WSACleanup();
system("pause");
exit(0);
}
else
{
cout << buf << endl;
}
}
}
2. 发信息子程序
void clientSend()
{
while (true)
{
string buf;
cin >> buf;
int res = send(pubServerSock, buf.c_str(), strlen(buf.c_str()), 0);
if (SOCKET_ERROR == res)
{
cout << "程序运行失败或链接中断。。。" << endl;
closesocket(pubServerSock);
// closesocket(pubClientSock);
WSACleanup();
system("pause");
exit(0);
}
}
}
五、运行结果截图