先决条件: C / C++中的套接字编程
可以从服务器发送数据并从客户端接收响应。类似地,客户端也可以往返发送和接收数据。在这里,我们将讨论在C / C++中使用Win32线程的方法。
方法:
- 使用CreateThread函数可为进程创建新线程。
- CreateThread方法必须指定新线程要执行的代码的起始地址。以下是CreateThread函数的原型:
HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId );
- 然后使用WaitForSingleObject函数以从客户端接收的对象形式返回消息,以从客户端接收数据。以下是WaitForSingleObject函数的原型:
DWORD WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds );
创建服务器程序
在服务器程序中,我们将使用两个线程,一个用于向客户端发送数据,另一个用于从客户端接收数据。当客户端和服务器都键入“ exit ”时,通信过程停止。
下面是服务器程序的实现:
Server
// C++ program to create Server
#include
#include
#include
using namespace std;
// Function that receive data
// from client
DWORD WINAPI serverReceive(LPVOID lpParam)
{
// Created buffer[] to
// receive message
char buffer[1024] = { 0 };
// Created client socket
SOCKET client = *(SOCKET*)lpParam;
// Server executes continuously
while (true) {
// If received buffer gives
// error then return -1
if (recv(client, buffer, sizeof(buffer), 0)
== SOCKET_ERROR) {
cout << "recv function failed with error "
<< WSAGetLastError() << endl;
return -1;
}
// If Client exits
if (strcmp(buffer, "exit") == 0) {
cout << "Client Disconnected."
<< endl;
break;
}
// Print the message
// given by client that
// was stored in buffer
cout << "Client: " << buffer << endl;
// Clear buffer message
memset(buffer, 0,
sizeof(buffer));
}
return 1;
}
// Function that sends data to client
DWORD WINAPI serverSend(LPVOID lpParam)
{
// Created buffer[] to
// receive message
char buffer[1024] = { 0 };
// Created client socket
SOCKET client = *(SOCKET*)lpParam;
// Server executes continuously
while (true) {
// Input message server
// wants to send to client
gets(buffer);
// If sending failed
// return -1
if (send(client,
buffer,
sizeof(buffer), 0)
== SOCKET_ERROR) {
cout << "send failed with error "
<< WSAGetLastError() << endl;
return -1;
}
// If server exit
if (strcmp(buffer, "exit") == 0) {
cout << "Thank you for using the application"
<< endl;
break;
}
}
return 1;
}
// Driver Code
int main()
{
// Data
WSADATA WSAData;
// Created socket server
// and client
SOCKET server, client;
// Socket address for server
// and client
SOCKADDR_IN serverAddr, clientAddr;
WSAStartup(MAKEWORD(2, 0), &WSAData);
// Making server
server = socket(AF_INET,
SOCK_STREAM, 0);
// If invalid socket created,
// return -1
if (server == INVALID_SOCKET) {
cout << "Socket creation failed with error:"
<< WSAGetLastError() << endl;
return -1;
}
serverAddr.sin_addr.s_addr = INADDR_ANY;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(5555);
// If socket error occurred,
// return -1
if (bind(server,
(SOCKADDR*)&serverAddr,
sizeof(serverAddr))
== SOCKET_ERROR) {
cout << "Bind function failed with error: "
<< WSAGetLastError() << endl;
return -1;
}
// Get the request from
// server
if (listen(server, 0)
== SOCKET_ERROR) {
cout << "Listen function failed with error:"
<< WSAGetLastError() << endl;
return -1;
}
cout << "Listening for
incoming connections...." << endl;
// Create buffer[]
char buffer[1024];
// Intialise client address
int clientAddrSize = sizeof(clientAddr);
// If connection established
if ((client = accept(server,
(SOCKADDR*)&clientAddr,
&clientAddrSize))
!= INVALID_SOCKET) {
cout << "Client connected!" << endl;
cout << "Now you can use our live chat application."
<< "Enter \"exit\" to disconnect" << endl;
// Create variable of
// type DWORD
DWORD tid;
// Create Thread t1
HANDLE t1 = CreateThread(NULL,
0,
serverReceive,
&client,
0,
&tid);
// If created thread
// is not created
if (t1 == NULL) {
cout << "Thread Creation Error: "
<< WSAGetLastError() << endl;
}
// Create Thread t2
HANDLE t2 = CreateThread(NULL,
0,
serverSend,
&client,
0,
&tid);
// If created thread
// is not created
if (t2 == NULL) {
cout << "Thread Creation Error: "
<< WSAGetLastError() << endl;
}
// Received Objects
// from client
WaitForSingleObject(t1,
INFINITE);
WaitForSingleObject(t2,
INFINITE);
// Close the socket
closesocket(client);
// If socket closing
// failed.
if (closesocket(server)
== SOCKET_ERROR) {
cout << "Close socket failed with error: "
<< WSAGetLastError() << endl;
return -1;
}
WSACleanup();
}
}
Client
// C++ program to create client
#include
#include
#include
using namespace std;
// Function that receive data from server
DWORD WINAPI clientReceive(LPVOID lpParam)
{
// Created buffer[] to
// receive message
char buffer[1024] = { 0 };
// Created server socket
SOCKET server = *(SOCKET*)lpParam;
// Client executes continuously
while (true) {
// If received buffer gives
// error then return -1
if (recv(server, buffer,
sizeof(buffer), 0)
== SOCKET_ERROR) {
cout << "recv function failed with error: "
<< WSAGetLastError()
<< endl;
return -1;
}
// If Server exits
if (strcmp(buffer, "exit") == 0) {
cout << "Server disconnected."
<< endl;
return 1;
}
// Print the message
// given by server that
// was stored in buffer
cout << "Server: " << buffer << endl;
// Clear buffer message
memset(buffer, 0, sizeof(buffer));
}
return 1;
}
// Function that sends data to server
DWORD WINAPI clientSend(LPVOID lpParam)
{
// Created buffer[] to
// receive message
char buffer[1024] = { 0 };
// Created server socket
SOCKET server = *(SOCKET*)lpParam;
// Client executes continuously
while (true) {
// Input message client
// wants to send to server
gets(buffer);
// If sending failed
// return -1
if (send(server,
buffer,
sizeof(buffer), 0)
== SOCKET_ERROR) {
cout << "send failed with error: "
<< WSAGetLastError() << endl;
return -1;
}
// If client exit
if (strcmp(buffer, "exit")
== 0) {
cout << "Thank you for using the application"
<< endl;
break;
}
}
return 1;
}
// Driver Code
int main()
{
// Input data
WSADATA WSAData;
// Created socket server
SOCKET server;
SOCKADDR_IN addr;
WSAStartup(MAKEWORD(2, 0), &WSAData);
// If invalid socket created,
// return -1
if ((server = socket(AF_INET,
SOCK_STREAM, 0))
== INVALID_SOCKET) {
cout << "Socket creation failed with error: "
<< WSAGetLastError() << endl;
return -1;
}
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_family = AF_INET;
addr.sin_port = htons(5555);
// If connection failed
if (connect(server,
(SOCKADDR*)&addr,
sizeof(addr))
== SOCKET_ERROR) {
cout << "Server connection failed with error: "
<< WSAGetLastError() << endl;
return -1;
}
// If connection established
cout << "Connected to server!"
<< endl;
cout << "Now you can use our live chat application."
<< " Enter \"exit\" to disconnect"
<< endl;
DWORD tid;
// Create Thread t1
HANDLE t1 = CreateThread(NULL,
0,
clientReceive,
&server,
0, &tid);
// If created thread
// is not created
if (t1 == NULL)
cout << "Thread creation error: "
<< GetLastError();
// Create Thread t2
HANDLE t2 = CreateThread(NULL,
0,
clientSend,
&server,
0, &tid);
// If created thread
// is not created
if (t2 == NULL)
cout << "Thread creation error: "
<< GetLastError();
// Received Objects
// from client
WaitForSingleObject(t1, INFINITE);
WaitForSingleObject(t2, INFINITE);
// Socket closed
closesocket(server);
WSACleanup();
}
使用以下命令运行ServerApplication.cpp文件:
g++ ServerApplication.cpp -lws2_32
创建客户端程序
在客户端程序中,我们将使用两个线程,一个用于将数据发送到服务器,另一个用于从服务器接收数据。当服务器和客户端都键入“ exit ”时,通信过程停止。
客户
// C++ program to create client
#include
#include
#include
using namespace std;
// Function that receive data from server
DWORD WINAPI clientReceive(LPVOID lpParam)
{
// Created buffer[] to
// receive message
char buffer[1024] = { 0 };
// Created server socket
SOCKET server = *(SOCKET*)lpParam;
// Client executes continuously
while (true) {
// If received buffer gives
// error then return -1
if (recv(server, buffer,
sizeof(buffer), 0)
== SOCKET_ERROR) {
cout << "recv function failed with error: "
<< WSAGetLastError()
<< endl;
return -1;
}
// If Server exits
if (strcmp(buffer, "exit") == 0) {
cout << "Server disconnected."
<< endl;
return 1;
}
// Print the message
// given by server that
// was stored in buffer
cout << "Server: " << buffer << endl;
// Clear buffer message
memset(buffer, 0, sizeof(buffer));
}
return 1;
}
// Function that sends data to server
DWORD WINAPI clientSend(LPVOID lpParam)
{
// Created buffer[] to
// receive message
char buffer[1024] = { 0 };
// Created server socket
SOCKET server = *(SOCKET*)lpParam;
// Client executes continuously
while (true) {
// Input message client
// wants to send to server
gets(buffer);
// If sending failed
// return -1
if (send(server,
buffer,
sizeof(buffer), 0)
== SOCKET_ERROR) {
cout << "send failed with error: "
<< WSAGetLastError() << endl;
return -1;
}
// If client exit
if (strcmp(buffer, "exit")
== 0) {
cout << "Thank you for using the application"
<< endl;
break;
}
}
return 1;
}
// Driver Code
int main()
{
// Input data
WSADATA WSAData;
// Created socket server
SOCKET server;
SOCKADDR_IN addr;
WSAStartup(MAKEWORD(2, 0), &WSAData);
// If invalid socket created,
// return -1
if ((server = socket(AF_INET,
SOCK_STREAM, 0))
== INVALID_SOCKET) {
cout << "Socket creation failed with error: "
<< WSAGetLastError() << endl;
return -1;
}
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_family = AF_INET;
addr.sin_port = htons(5555);
// If connection failed
if (connect(server,
(SOCKADDR*)&addr,
sizeof(addr))
== SOCKET_ERROR) {
cout << "Server connection failed with error: "
<< WSAGetLastError() << endl;
return -1;
}
// If connection established
cout << "Connected to server!"
<< endl;
cout << "Now you can use our live chat application."
<< " Enter \"exit\" to disconnect"
<< endl;
DWORD tid;
// Create Thread t1
HANDLE t1 = CreateThread(NULL,
0,
clientReceive,
&server,
0, &tid);
// If created thread
// is not created
if (t1 == NULL)
cout << "Thread creation error: "
<< GetLastError();
// Create Thread t2
HANDLE t2 = CreateThread(NULL,
0,
clientSend,
&server,
0, &tid);
// If created thread
// is not created
if (t2 == NULL)
cout << "Thread creation error: "
<< GetLastError();
// Received Objects
// from client
WaitForSingleObject(t1, INFINITE);
WaitForSingleObject(t2, INFINITE);
// Socket closed
closesocket(server);
WSACleanup();
}
使用以下命令运行ClientApplication.cpp文件:
g++ ClientApplication.cpp -lws2_32
服务器与客户端之间的通信后输出
左侧命令提示符是ServerApplication ,右侧命令提示符是ClientApplication 。
想要从精选的最佳视频中学习并解决问题,请查看有关从基础到高级C++的C++基础课程以及有关语言和STL的C++ STL课程。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程” 。