// tcpSocketServer.cpp
#include
#include
#include
#pragma comment(lib,"ws2_32.lib")
#define IP_ADDRESS "127.0.0.1"
#define PORT 5678
static DWORD WINAPI RecvThread(void *Param);
static DWORD WINAPI SendThread(void *Param);
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int retCode;
SOCKET socketServer;
SOCKADDR_IN addrSrv;
SOCKADDR_IN addrClient;
int len = sizeof(SOCKADDR);
SOCKET socketConnection;
std::vector threadHandleSet;
std::vector clientSocketSet;
wVersionRequested = MAKEWORD(2, 2);
retCode = WSAStartup(wVersionRequested, &wsaData);
if (retCode != 0)
{
fprintf(stderr, "Load WSADTATA failed!\n");
return;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
fprintf(stderr, "WSADTATA version error!\n");
WSACleanup();
return;
}
socketServer = socket(AF_INET, SOCK_STREAM, 0);//创建套接字
if (socketServer == INVALID_SOCKET)
{
fprintf(stderr, "invalid socket !\n");
WSACleanup();
return;
}
//addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrSrv.sin_addr.S_un.S_addr = inet_addr(IP_ADDRESS);
addrSrv.sin_family = AF_INET;//将sin_family字段设置为AF_INET,代表WinSock使用的是IP地址族
addrSrv.sin_port = htons(PORT);//端口号
retCode = bind(socketServer, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));//绑定套接字到一个IP地址和一个端口上
if (retCode == SOCKET_ERROR)
{
printf("bind error !");
closesocket(socketServer);
WSACleanup();
return;
}
retCode = listen(socketServer, 2);//将套接字设置为监听模式等待连接请求
if (retCode == SOCKET_ERROR)
{
printf("listen error !");
closesocket(socketServer);
WSACleanup();
return;
}
printf("Tcp server is running....\n");
while (1)
{
//请求到来后,接收连接请求,返回一个新的对应于此次连接的套接字
socketConnection = accept(socketServer, (SOCKADDR*)&addrClient, &len);
if (socketConnection == INVALID_SOCKET)
{
printf("accept error, continue to accept new client !");
continue;
}
printf("接受到一个连接:%s \r\n", inet_ntoa(addrClient.sin_addr));
clientSocketSet.push_back(socketConnection);
//创建一个子线程调用RecvThread函数,专门用来接收消息
HANDLE recvThreadHandle = CreateThread(NULL, 0, RecvThread, &socketConnection, 0, NULL);
if (recvThreadHandle == NULL)
{
fprintf(stderr, "Create recive data thread failed!\n");
}
threadHandleSet.push_back(recvThreadHandle);
HANDLE sendThreadHandle = CreateThread(NULL, 0, SendThread, &socketConnection, 0, NULL);
if (sendThreadHandle == NULL)
{
fprintf(stderr, "Create recive data thread failed!\n");
}
threadHandleSet.push_back(sendThreadHandle);
}
fprintf(stderr, "main thread to wait sub thread to finish.\n");
for (int i = 0; i < threadHandleSet.size(); i++)
{
if (threadHandleSet[i])
{
WaitForSingleObject(threadHandleSet[i], INFINITE);
CloseHandle(threadHandleSet[i]);
fprintf(stderr, "thread %d close()\n", i + 1);
}
}
for (int i = 0; i < clientSocketSet.size(); i++)
{
closesocket(clientSocketSet[i]);
fprintf(stderr, "socket %d close.\n", i + 1);
}
closesocket(socketServer);
WSACleanup();//关闭加载的套接字库
}
static DWORD WINAPI RecvThread(void *Param){
SOCKET socketConnection = *((SOCKET *)Param); //设置socket
char recvBuf[1024];
int ret;
while (1)
{
ret = recv(socketConnection, recvBuf, sizeof(recvBuf), 0);
if (ret > 0)
{
recvBuf[ret] = 0x00;
fprintf(stdout, "recivce data from client success!\n");
printf("客户端说:%s\n", recvBuf);
}
else if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))
{
fprintf(stderr, "Client has disconneted, recive data failed!\n");
break;
}
else if (ret == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
{
fprintf(stdout, "非阻塞类型返回\n");
break;
}
}
fprintf(stderr, "接收数据子线程退出\n");
return 0;
}
static DWORD WINAPI SendThread(void *Param)
{
SOCKET socketConnection = *((SOCKET *)Param);
int retCode;
char sendBuf[128];
while (1)
{
memset(sendBuf, 0, sizeof(sendBuf));
printf("输入要发送给客户端的消息:\n");
fgets(sendBuf, sizeof(sendBuf), stdin);
int length = strlen(sendBuf);
if (length < 2)
{
printf("不能发送空消息.\n");
continue;
}
retCode = send(socketConnection, sendBuf, length, 0);
if (retCode == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)
{
fprintf(stderr, "Client has disconneted, send data to client failed!\n");
break;
}
else if (retCode == SOCKET_ERROR)
{
printf("Send data to client failed!\n");
break;
}
if (retCode != SOCKET_ERROR)
{
printf("Send data to client finished.\n");
}
}
fprintf(stderr, "发送数据子线程退出\n");
return 0;
}
// tcpSocketClient.cpp
#include
#include
#pragma comment(lib,"ws2_32.lib")
#define IP_ADDRESS "127.0.0.1"
#define PORT 5678
static DWORD WINAPI RecvThread(void *Param);
void main( )
{
WORD wVersionRequested;
WSADATA wsaData;
SOCKET socketClient;
SOCKADDR_IN addrSrv;
char sendBuf[50];
int retCode;
wVersionRequested = MAKEWORD(2, 2);
retCode = WSAStartup(wVersionRequested, &wsaData);
if (retCode != 0)
{
fprintf(stderr, "Load WSADTATA failed!\n");
return;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){
fprintf(stderr, "WSADTATA version error!\n");
WSACleanup();
return;
}
socketClient = socket(AF_INET, SOCK_STREAM, 0);
if (socketClient == INVALID_SOCKET)
{
fprintf(stderr, "invalid socket !\n");
WSACleanup();
return;
}
addrSrv.sin_addr.S_un.S_addr = inet_addr(IP_ADDRESS);//IP地址
addrSrv.sin_family = AF_INET; //将sin_family字段设置为AF_INET,代表WinSock使用的是IP地址族
addrSrv.sin_port = htons(PORT); //端口号
//向服务器端发出连接请求
retCode = connect(socketClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
if (retCode == SOCKET_ERROR)
{
fprintf(stderr, "Connet server error!%d\n", GetLastError());
closesocket(socketClient);
WSACleanup();
return;
}
//创建子线程调用RecvThread函数,专门用来接收服务器端发过来的消息
HANDLE recvDataThreadHandle = CreateThread(NULL, 0, RecvThread, &socketClient, 0, NULL);
if (recvDataThreadHandle == NULL)
fprintf(stderr, "Create recive data thread failed!\n");
//发送消息在主线程当中实现
while (1)
{
memset(sendBuf, 0, sizeof(sendBuf));
printf("请输入要发给服务器端的消息:\n");
fgets(sendBuf, sizeof(sendBuf), stdin);
int length = strlen(sendBuf);
if (length < 2)
{
printf("不能发送空消息.\n");
continue;
}
retCode = send(socketClient, sendBuf, strlen(sendBuf) + 1, 0);//发送消息
if (retCode == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)
{
fprintf(stderr, "Server has disconneted, send data to server failed!\n");
break;
}
else if (retCode == SOCKET_ERROR)
{
printf("Send data to server failed!\n");
break;
}
if (retCode != SOCKET_ERROR)
{
printf("Send data to server finished.\n");
}
}
if (recvDataThreadHandle)
{
/// 同步子线程,再关闭
WaitForSingleObject(recvDataThreadHandle, INFINITE);
CloseHandle(recvDataThreadHandle);
}
closesocket(socketClient);
WSACleanup();//关闭加载的套接字库
}
static DWORD WINAPI RecvThread(void *Param)
{
SOCKET socketConnection = *((SOCKET *)Param);
char recvBuf[1024];
int ret;
while (1)
{
ret = recv(socketConnection, recvBuf, sizeof(recvBuf), 0);
if (ret > 0)
{
recvBuf[ret] = 0x00;
fprintf(stdout, "recivce data from server success!\n");
printf("服务器说:%s\n", recvBuf);
}
else if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))
{
fprintf(stderr, "Server has disconneted, recive data failed!\n");
break;
}
else if (ret == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
{
fprintf(stdout, "非阻塞类型返回\n");
break;
}
}
return 0;
}