Windows网络通信(Socket)入门代码

随便写写,非常简单,可以作为网络通信入门代码。

代码分为两部分:一个服务端;一个客户端。分别建立两个工程,直接编译运行就可以见到效果!

其中用到了多线程的一些技术,关于线程同步这方面暂未考虑!

/************************************************************************/
/*Server.cpp                                                            */
/************************************************************************/

#include <WinSock2.h>
#include <iostream>
#include <string>
#include <process.h>
#include <list>
//using namespace std;
//#pragma comment (lib, "wsock32.lib")	//或者 连接器-》输入-》附加依赖项中加入wsock32.lib
#pragma comment (lib, "WS2_32.lib")

#define MAXBUF 32767

int nFlag = 1;		//0表示退出
std::list<SOCKET> ConnSocketLst;
SOCKET		ListeningSocket;

//接受数据
UINT WINAPI RecvData(LPVOID pParam);
//发送数据
UINT WINAPI SendData(LPVOID pParam);

int main()
{
	WSADATA		WsaData;
	//SOCKET		ListeningSocket;
	//SOCKET		NewConnectSocket;
	SOCKADDR_IN	ServerAddr;
	SOCKADDR_IN	ClientAddr;
	int			Port = 5678;
	//初始化版本2.2
	if (0 != WSAStartup(MAKEWORD(2, 2), &WsaData))
	{
		std::cout << "网络初始化失败\n";
		getchar();
		return -1;
	}
	//创建一个新的套接字来监听客户机的连接
	ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	//建立一个SOCKADDR_IN结构,来告知bind函数要在5678端口上监听所有接口的连接
	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_port = htons(Port);	//主机字节顺序转换为网络字节顺序
	ServerAddr.sin_addr.s_addr = htonl(ADDR_ANY);
	//使用bind函数将这个地址信息与套接字关联起来
	bind(ListeningSocket, (SOCKADDR*)&ServerAddr, sizeof(SOCKADDR));
	//监听客户机
	listen(ListeningSocket, 5);
	//得到尺寸
	int ClientLen = sizeof(SOCKADDR_IN);
	//创建线程,发送数据
	HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, SendData, NULL, 0, NULL);
	//循环得到客户端的连接
	while(0 != nFlag)
	{
		//连接到达时接受一个新连接
		SOCKET NewConnectSocket = accept(ListeningSocket, (SOCKADDR*)&ClientAddr, &ClientLen);
		ConnSocketLst.push_back(NewConnectSocket);
		//创建线程,接受数据
		HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, RecvData, (LPVOID)(&NewConnectSocket), 0, NULL);
	}

	//关闭套接字
	std::list<SOCKET>::iterator it = ConnSocketLst.begin();
	for (; it != ConnSocketLst.end();)
	{
		closesocket(*it);
		ConnSocketLst.erase(it++);
	}
	ConnSocketLst.clear();
	closesocket(ListeningSocket);
	//清理
	WSACleanup();

	getchar();
	return 0;
}

//接受数据
UINT WINAPI RecvData(LPVOID pParam)
{
	//得到套接字
	SOCKET Socket = *((SOCKET*)pParam);
	//获得数据
	char buf[MAXBUF] = {0};
	while (1)
	{
		int nLen = recv(Socket, buf, MAXBUF, 0);// | MSG_PEEK | MSG_OOB);
		if (0 < nLen)
		{
			buf[nLen] = '\0';
			std::cout << buf << "\n";
			SendData(buf);
			//是否退出
			if (0 == strcmp(buf, "客户端:\n  quit\n"))
			{
				break;
			}
		}
		else
		{
			std::cout << "接收数据失败\n";
			break;
		}
	}

	closesocket(Socket);
	ConnSocketLst.remove(Socket);
/*
	std::list<SOCKET>::iterator it = ConnSocketLst.begin();
	for (; it != ConnSocketLst.end(); it++)
	{
		if (*it == Socket)
		{
			ConnSocketLst.erase(it);
			break;
		}
	}
*/
	//_endthreadex(0);
	return 0;
}

//发送数据
UINT WINAPI SendData(LPVOID pParam)
{
	//得到套接字
	char *SendBuf = (char*)pParam;
	if (SendBuf == NULL)
	{
		//将要发送的数据
		std::string strSend;
		//循环输入并发送数据
		while (0 != nFlag)
		{
			//清空以前的数据并重新输入数据
			strSend.clear();
			for (;;)
			{
				char cTemp = getchar();
				strSend.append(1, cTemp);
				if (cTemp == '\n') 
				{
					strSend.append(1, '\0');
					break;
				}
			}
			//设置标志(是否退出)
			nFlag = strcmp(strSend.c_str(), "quit\n");
			//发送数据前准备
			strSend = "服务端:\n  " + strSend;
			//std::cout << strSend.c_str() << "\n";
			int nLeft = (int)strSend.length();
			//发送数据
			std::list<SOCKET>::iterator it = ConnSocketLst.begin();
			for (; it != ConnSocketLst.end(); it++)
			{
				int nRet = send(*it, strSend.c_str(), nLeft, 0);// | MSG_DONTROUTE | MSG_OOB);
				if (nRet == SOCKET_ERROR) {
					std::cout << "发送数据失败\n";
				}
			}
		}
		//关闭监听套接字
		closesocket(ListeningSocket);
	}
	else
	{
		int nLeft = (int)strlen(SendBuf);
		//发送数据
		std::list<SOCKET>::iterator it = ConnSocketLst.begin();
		for (; it != ConnSocketLst.end(); it++)
		{
			int nRet = send(*it, SendBuf, nLeft, 0);// | MSG_DONTROUTE | MSG_OOB);
			if (nRet == SOCKET_ERROR) {
				std::cout << "发送数据失败\n";
			}
		}
	}

	return 0;
}
/************************************************************************/
/*Client.cpp                                                            */
/************************************************************************/

#include <WinSock2.h>
#include <iostream>
#include <string>
#include <process.h>

#pragma comment (lib, "WS2_32.lib")

#define MAXBUF 32767

int		nFlag = 1;		//0表示退出
HANDLE	g_Mutex = CreateMutex(NULL, TRUE, NULL);	//创建互斥对象

//接受数据
UINT WINAPI RecvData(LPVOID pParam);
//发送数据
UINT SendData(LPVOID pParam);

int main()
{
	WSADATA		WsaData;
	SOCKET		ClientSocket;
	SOCKADDR_IN	ServerAddr;
	int			Port = 5678;
	//初始化版本2.2
	if (0 != WSAStartup(MAKEWORD(2, 2), &WsaData))
	{
		std::cout << "网络初始化失败\n";
		goto END;
	}
	//创建一个新的套接字来建立客户机的连接
	ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	//建立一个SOCKADDR_IN结构,来连接服务器
	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_port = htons(Port);	//主机字节顺序转换为网络字节顺序
	ServerAddr.sin_addr.s_addr = inet_addr(("127.0.0.1"));
	//用套接字创建一个到服务器的连接
	if (0 != connect(ClientSocket, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr)))
	{
		std::cout << "连接服务器失败\n";
		goto END;
	}
	
	//创建线程,接受数据
	HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, RecvData, (LPVOID)(&ClientSocket), 0, NULL);
	//发送数据
	SendData(&ClientSocket);
	//等待接收数据的线程结束
	while (WAIT_OBJECT_0 != WaitForSingleObject(hThread, INFINITE)) { }

END:
	//关闭套接字
	closesocket(ClientSocket);
	//清理
	WSACleanup();
	//释放互斥对象
	ReleaseMutex(g_Mutex);

	getchar();
	return 0;
}

//接受数据
UINT WINAPI RecvData(LPVOID pParam)
{
	//得到套接字
	SOCKET Socket = *((SOCKET*)pParam);
	//获得数据
	char buf[MAXBUF] = {0};
	while (1)
	{
		int nLen = recv(Socket, buf, MAXBUF, 0);// | MSG_PEEK | MSG_OOB);
		if (0 < nLen)
		{
			buf[nLen] = '\0';
			std::cout << buf << "\n";
			//是否退出
			if (0 == strcmp(buf, "服务端:\n  quit\n"))
			{
				break;
			}
		}
		else
		{
			std::cout << "与服务器断开连接\n";
			break;
		}
	}
	nFlag = 0;
	return 0;
}

//发送数据
UINT SendData(LPVOID pParam)
{
	//得到套接字
	SOCKET Socket = *((SOCKET*)pParam);
	//将要发送的数据
	std::string strSend;
	//循环输入并发送数据
	while (0 != nFlag)
	{
		//清空以前的数据并重新输入数据
		strSend.clear();
		for (;;)
		{
			char cTemp = getchar();
			strSend.append(1, cTemp);
			if (cTemp == '\n') 
			{
				strSend.append(1, '\0');
				break;
			}
		}
		//发送数据前准备
		strSend = "客户端:\n  " + strSend;
		int nLeft = (int)strSend.length();
		int nRet = send(Socket, strSend.c_str(), nLeft, 0);// | MSG_DONTROUTE | MSG_OOB);
		if (nRet == SOCKET_ERROR) {
			std::cout << "发送数据失败\n";
		}
	}

	return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值