前言
不得不承认作为一个前端开发,仍有一个后台开发的梦。从socket通信开始学习,在工作之余补充学习点相关知识,记录下学习的过程。
服务端
服务器代码如下,在设置listen之后,通过accept获取对应的socket连接并创建线程进行通信,通信完成后关闭对应线程。
// socket_service.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <stdio.h>
#include <Winsock2.h>
#pragma comment(lib, "ws2_32.lib") #define LISTEN_MAX_COUNT 5 DWORD WINAPI AnswerThread(LPVOID lparam)
{
printf("Thread ID:%4d create!\n", GetCurrentThreadId());
int ret;
char buf[] = { };
char sendBuf[] = { };
SOCKET clientSocket = (SOCKET)(LPVOID)lparam;
while (true)
{
memset(buf, , sizeof(buf));
ret = recv(clientSocket, buf, sizeof(buf), );
if (ret<=)
{
break;
}
printf("revc: %s\n", buf);
sprintf_s(sendBuf, "Thread ID:%4d revced", GetCurrentThreadId());
ret = send(clientSocket, sendBuf, strlen(sendBuf) + sizeof(char), );
if (ret <= )
{
break;
}
}
printf("Thread ID:%4d stop!\n", GetCurrentThreadId());
closesocket(clientSocket);
return ;
} int _tmain(int argc, _TCHAR* argv[])
{ WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(, );
if (WSAStartup(wVersionRequested, &wsaData) == INVALID_SOCKET)
{
return ;
} if (LOBYTE(wsaData.wVersion) != ||
HIBYTE(wsaData.wVersion) != ) {
WSACleanup();
return ;
}
SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, );
int len = sizeof(SOCKADDR);
SOCKADDR_IN clientAddr;
SOCKADDR_IN serviceAddr;
serviceAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
serviceAddr.sin_family = AF_INET;
serviceAddr.sin_port = htons(); if (bind(sockSrv, (SOCKADDR*)&serviceAddr, len) == INVALID_SOCKET)
{
printf("failed bind!\n");
closesocket(sockSrv);
WSACleanup();
return ;
}
if (listen(sockSrv, LISTEN_MAX_COUNT) == SOCKET_ERROR) {
printf("Listen failed with error: %ld\n", WSAGetLastError());
closesocket(sockSrv);
WSACleanup();
return ;
} SOCKET sockClient;
HANDLE hThread = NULL;
DWORD dwThreadId;
while ()
{
sockClient = accept(sockSrv, (SOCKADDR*)&clientAddr, &len);
Sleep();
hThread = CreateThread(NULL, NULL, AnswerThread, (LPVOID)sockClient, , &dwThreadId);
if (hThread == NULL)
{
printf("CreatThread AnswerThread() failed.\n");
}
} closesocket(sockSrv);
WSACleanup();
return ;
}
客户端
客户端代码如下,在连接成功后,循环输入进行通信对话。
// socket_client.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <stdio.h>
#include <Winsock2.h> #pragma comment( lib, "ws2_32.lib" ) int _tmain(int argc, _TCHAR* argv[])
{ WORD wVersionRequested;
WSADATA wsaData;
int err; wVersionRequested = MAKEWORD(, );
if (WSAStartup(wVersionRequested, &wsaData) == INVALID_SOCKET)
{
return -;
} if (LOBYTE(wsaData.wVersion) != ||
HIBYTE(wsaData.wVersion) != ) {
WSACleanup();
return -;
} SOCKET sockClient = socket(AF_INET, SOCK_STREAM, );
int len = sizeof(SOCKADDR); SOCKADDR_IN local;
local.sin_addr.S_un.S_addr = inet_addr("192.168.1.15");
local.sin_family = AF_INET;
local.sin_port = htons(); if (connect(sockClient, (SOCKADDR*)&local, len) == INVALID_SOCKET)
{
printf("connect error/n");
return ;
} char inputBuf[];
char recvBuf[];
int ret;
// while (scanf_s("%s", inputBuf, sizeof(inputBuf)) != EOF)
while (gets_s(inputBuf))
{
if (strcmp(inputBuf, "stop") ==)
{
break;
}
ret = send(sockClient, inputBuf, strlen(inputBuf) + sizeof(char), );
if (ret<=)
{
printf("send failed!\n");
break;
}
ret = recv(sockClient, recvBuf, sizeof(recvBuf), );
if (ret <= )
{
printf("recv failed!\n");
break;
}
printf("my reply is : %s\n", recvBuf);
//printf("%s\n", inet_ntoa(local.sin_addr));
} closesocket(sockClient);
WSACleanup();
return ;
}
测试
Hello World!!
1、开启多个客户端,可以看到服务器如下输出多个线程的创建。
2、客户端输入hello world!,可以得到服务器回复,并告知哪个服务器线程接收了消息。
3、关闭其中一个客户端,可以看到对应线程也关闭了。
4、关闭服务端后,可以端输入任意内容,可以看到客户端也收到提示发送失败并关闭。