在server端创建一个接收线程,一个发送线程
client端依旧单线程
server.cpp
// Thread.cpp : 定义控制台应用程序的入口点。
//
//#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
#define buf_size 30
#define PORT 4000
#define IP_ADDRESS "127.0.0.1"
//创建线程
DWORD WINAPI Recv (LPVOID ipParameter)
{
SOCKET clientSocket = (SOCKET)ipParameter;
int RET = 0;
char RecvBuffer[buf_size];
//初始化 recvBuffer
while(true){
memset(RecvBuffer,0x00,sizeof(RecvBuffer));
RET = recv(clientSocket,RecvBuffer,buf_size,0);
if(RET == 0||RET == SOCKET_ERROR)
{
cout<<"客户端退出"<<endl;
break;
}
cout<<"接受的消息为"<<RecvBuffer<<endl;
}
return 0;
}
//发送函数
DWORD WINAPI Send (LPVOID ipParameter)
{
SOCKET clientSocket = (SOCKET)ipParameter;
int RET = 0;
char SendBuffer[buf_size];
//初始化 recvBuffer
while(true){
memset(SendBuffer,0x00,sizeof(SendBuffer));
gets(SendBuffer);
RET = send(clientSocket,SendBuffer,buf_size,0);
if(RET == 0||RET == SOCKET_ERROR)
{
cout<<"客户端退出"<<endl;
break;
}
cout<<"发送的消息为"<<SendBuffer<<endl;
}
return 0;
}
int main(void)
{
WSADATA WSA;
SOCKET severScoket,clientSocket;
struct sockaddr_in LocalAddr,clientAddr;
int AddrLen = 0;
HANDLE hThread1 = NULL;
HANDLE hThread2 = NULL;
int RET = 0;
//init windows socket
if (WSAStartup(MAKEWORD(2,2),&WSA)!= 0 )
{
cout<<"init failed"<<endl;
return -1;
}
//creat socket
severScoket = socket(AF_INET,SOCK_STREAM,0);
if(severScoket == INVALID_SOCKET)
{
cout<<"creat failed"<<GetLastError()<<endl;
return -1;
}
LocalAddr.sin_family = AF_INET;
LocalAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
LocalAddr.sin_port = htons(PORT);
memset(LocalAddr.sin_zero,0x00,8);
//bind socket
RET = bind(severScoket,(struct sockaddr*)&LocalAddr,sizeof(LocalAddr));
if (RET != 0)
{
cout<<"bind failed";
return -1;
}
RET = listen(severScoket,5);
if (RET!= 0)
{
cout<<"listen failed";
return -1;
}
cout<<"服务器已启动"<<endl;
while(true)
{
AddrLen = sizeof(clientAddr);
clientSocket = accept(severScoket,(struct sockaddr*)&clientAddr,&AddrLen);
if (clientSocket ==INVALID_SOCKET)
{
cout<<"accept failed";
break;
}
cout<<"客户端连接"<<inet_ntoa(clientAddr.sin_addr)<<"."<<clientAddr.sin_port<<endl;
hThread1 = CreateThread(NULL,0,Recv,(LPVOID)clientSocket,0,NULL);
if(hThread1 == NULL)
{
cout<<"creat thread failed"<<endl;
break;
}
CloseHandle(hThread1);
hThread2 = CreateThread(NULL,0,Send,(LPVOID)clientSocket,0,NULL);
if(hThread2 == NULL)
{
cout<<"creat thread failed"<<endl;
break;
}
CloseHandle(hThread2);
}
closesocket(severScoket);
closesocket(clientSocket);
WSACleanup();
return 0;
}
client.cpp
//#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
#define buf_size 30
#define PORT 4000
#define IP_ADDRESS "127.0.0.1"
int main(void)
{
WSADATA WSA;
SOCKET clientSocket;
struct sockaddr_in serveAddr;
int AddrLen = 0;
HANDLE hThread = NULL;
int RET = 0;
char SendBuffer[buf_size];
char RecvBuffer[buf_size];
//init windows socket
if (WSAStartup(MAKEWORD(2,2),&WSA)!= 0 )
{
cout<<"init failed"<<endl;
return -1;
}
//creat socket
clientSocket = socket(AF_INET,SOCK_STREAM,0);
if(clientSocket == INVALID_SOCKET)
{
cout<<"creat failed"<<GetLastError()<<endl;
return -1;
}
serveAddr.sin_family = AF_INET;
serveAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
serveAddr.sin_port = htons(PORT);
memset(serveAddr.sin_zero,0x00,8);
RET = connect(clientSocket,(struct sockaddr*)&serveAddr,sizeof(serveAddr));
if (RET != 0)
{
cout<<"connect failed";
return -1;
}
else{ cout<<"连接成功"<<endl;}
while(true)
{
ZeroMemory(SendBuffer,sizeof(SendBuffer));
gets(SendBuffer);
RET = send(clientSocket,SendBuffer,buf_size,0);
if (RET == SOCKET_ERROR)
{
cout<<"send to error"<<endl;
break;
}
cout<<"发送的消息为:"<<SendBuffer<<endl;
ZeroMemory(RecvBuffer,sizeof(RecvBuffer));
RET = recv(clientSocket,RecvBuffer,buf_size,0);
if (RET == SOCKET_ERROR)
{
cout<<"recv error"<<endl;
closesocket(clientSocket);
WSACleanup();
return -1;
// break;
}
cout<<"接收的消息为:"<<RecvBuffer<<endl;
}
closesocket(clientSocket);
WSACleanup();
return 0;
}
实验效果:
一个发送和接收是一个轮回。如果连续两次发送,那么对方必须要到第二轮回时候才能将缓冲器文本打印出来
for example:
现在服务端连续发送两次,如上所说,客户端要到第二次轮回才能显示服务器第二次发送的内容
客户端还未按回车前的状态:
按了回车后: