简单的 winsocket TCP通信

//服务器
#include<iostream>
#include<WinSock2.h>                    // socket 所需要的头文件
#pragma comment(lib,"WS2_32.lib")// link socket 库
#define PORT 9999 
#define BUFLEN 1024
using namespace std;
int main()
{
	WSADATA wsaData;
	// 1 启动并初始化winsock(WSAStarup)
	if (WSAStartup(MAKEWORD(2, 2), &wsaData))//成功返回0
	{
		return FALSE;
	}
	//2 创建套接字(socket)
	SOCKET sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if(INVALID_SOCKET == sServer)
	{
		WSACleanup();
		return FALSE;
	}
	//3 准备通信地址
	SOCKADDR_IN addrServer;
	addrServer.sin_family = AF_INET;
	addrServer.sin_port = htons(PORT);
	addrServer.sin_addr.s_addr = INADDR_ANY;//任意可用地址
   //4 绑定地址与socket(bind)
	if (SOCKET_ERROR==bind(sServer, (const sockaddr*)&addrServer, sizeof(SOCKADDR_IN)))
	{
		closesocket(sServer);
		WSACleanup();
		
		return FALSE;
	}
	//5 监听 (listen)
	if (SOCKET_ERROR == listen(sServer, SOMAXCONN))
	{
		closesocket(sServer);
		WSACleanup();
	}
	// 6 等待客户端连接(accpet)
	sockaddr_in addrClient;
	int addrClientLen = sizeof(addrClient);
	cout << "服务器启动成功,等待客户端连接中。。。。" << endl;
	SOCKET sClient = accept(sServer, (sockaddr *)&addrClient, &addrClientLen);
	if (INVALID_SOCKET == sClient)
	{
		cout << WSAGetLastError() << endl;
		closesocket(sServer);
		closesocket(sClient);
		WSACleanup();
		return FALSE;
	}
	//7 接收数据(recv)
	char recvBuf[BUFLEN];
	ZeroMemory(recvBuf, sizeof(recvBuf));
	if (SOCKET_ERROR == recv(sClient, recvBuf, sizeof(recvBuf), 0))
	{
		closesocket(sServer);
		closesocket(sClient);
		WSACleanup();
		return FALSE;
	}
	cout << "客户端(" << inet_ntoa(addrClient.sin_addr) << ":" << addrClient.sin_port << "):" << recvBuf << endl;
	//8 发送数据
	char sendBuf[BUFLEN] = "你好客户端!";
	if (SOCKET_ERROR==send(sClient, sendBuf, sizeof(sendBuf), 0))
	{
		closesocket(sServer);
		closesocket(sClient);
		WSACleanup();
		return FALSE;
	}
	system("pause");
	system("pause");
	return TRUE;
}
/*
注:1:MAKEWORD把参数组成一个WORD(双字节)类型数据并返回这个WORD类型数值,高位代表(修订本)号,低位字节指定主版本号(其代表)
2:socket(AF_INET,//The Internet Protocol version 4 (IPv4) address family
SOCK_STREAM,//, two-way,This socket type uses the Transmission Control Protocol (TCP) for the Internet address family (AF_INET or AF_INET6).
IPPROTO_TCP//The Transmission Control Protocol (TCP). This is a possible value when the af parameter is AF_INET or AF_INET6 and the type parameter is SOCK_STREAM.
)
*/
//客户端
#include<iostream>
#include<WinSock2.h>
#pragma comment(lib,"WS2_32.lib")
using namespace std;
#define BUFLEN 1024
#define PORT 9999 
void getIP(char*szHostaddress);
int main()
{

	WSADATA wsaData;
	// 1 启动并初始化winsock(WSAStarup)
	if (WSAStartup(MAKEWORD(2, 2), &wsaData))//成功返回0
	{
		return FALSE;
	}
	//2 创建套接字(socket)
	SOCKET sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (INVALID_SOCKET == sHost)
	{
		closesocket(sHost);
		WSACleanup();
		return FALSE;
	}
	//3 准备通信地址
	char szHostaddress[200];
	getIP(szHostaddress);
	SOCKADDR_IN addrServer;
	addrServer.sin_family = AF_INET;
	addrServer.sin_port = htons(PORT);
	addrServer.sin_addr.s_addr = inet_addr(szHostaddress);
	//4 连接服务器(connect)
	if (SOCKET_ERROR == connect(sHost, (const sockaddr*)&addrServer, sizeof(addrServer)))
	{
		closesocket(sHost);
		WSACleanup();
		return FALSE;
	}
	//5 发送数据 (send)
	char sendBuf[BUFLEN] = "你好服务器!";
	if (SOCKET_ERROR == send(sHost, sendBuf, sizeof(sendBuf), 0))
	{
		closesocket(sHost);
		WSACleanup();
		return FALSE;
	}
	cout << "客户端发送消息成功!" << endl;
	//7 接收数据(recv)
	char recvBuf[BUFLEN];
	ZeroMemory(recvBuf, sizeof(recvBuf));
	if (SOCKET_ERROR == recv(sHost, recvBuf, sizeof(recvBuf), 0))
	{
		closesocket(sHost);
		WSACleanup();
		return FALSE;
	}
	cout << "服务器发来的消息:" <<recvBuf<< endl;
	system("pause");
}
void getIP(char*szHostaddress){
	char szHostname[100];
	if (gethostname(szHostname, sizeof(szHostname)) != SOCKET_ERROR)//先得到主机名
	{
		HOSTENT *pHostEnt = gethostbyname(szHostname);//通过名字拿到地址
		if (pHostEnt != NULL)
		{
			sprintf(szHostaddress, "%d.%d.%d.%d",
				(pHostEnt->h_addr_list[0][0] & 0x00ff),
				(pHostEnt->h_addr_list[0][1] & 0x00ff),
				(pHostEnt->h_addr_list[0][2] & 0x00ff),
				(pHostEnt->h_addr_list[0][3] & 0x00ff));
		}
	}
	else
		return;
}


  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Winsock2 TCP服务器中向多个TCP客户端发送信息,可以使用一个循环来迭代每个客户端套接字,并使用send函数向每个客户端发送消息。以下是一个简单的示例代码: ```c #include <stdio.h> #include <winsock2.h> #define MAX_CLIENTS 10 int main() { WSADATA wsaData; SOCKET serverSocket, clientSockets[MAX_CLIENTS]; struct sockaddr_in serverAddr, clientAddr; char ip[INET_ADDRSTRLEN]; const char* message = "Hello, clients!"; // 初始化Winsock if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { printf("Failed to initialize winsock.\n"); return 1; } // 创建套接字 serverSocket = socket(AF_INET, SOCK_STREAM, 0); if (serverSocket == INVALID_SOCKET) { printf("Failed to create socket.\n"); WSACleanup(); return 1; } // 设置服务器地址和端口 serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(8080); // 例如,这里假设服务器监听端口为8080 serverAddr.sin_addr.s_addr = INADDR_ANY; // 绑定套接字到服务器地址和端口 if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) { printf("Failed to bind socket.\n"); closesocket(serverSocket); WSACleanup(); return 1; } // 监听连接 if (listen(serverSocket, SOMAXCONN) == SOCKET_ERROR) { printf("Failed to listen on socket.\n"); closesocket(serverSocket); WSACleanup(); return 1; } printf("Waiting for incoming connections...\n"); // 初始化客户端套接字数组 for (int i = 0; i < MAX_CLIENTS; ++i) { clientSockets[i] = INVALID_SOCKET; } while (1) { // 接受客户端连接 int clientAddrLen = sizeof(clientAddr); SOCKET clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientAddrLen); if (clientSocket == INVALID_SOCKET) { printf("Failed to accept client connection.\n"); closesocket(serverSocket); WSACleanup(); return 1; } // 获取客户端IP地址 const char* clientIP = inet_ntop(AF_INET, &(clientAddr.sin_addr), ip, INET_ADDRSTRLEN); if (clientIP == NULL) { printf("Failed to convert IP address to string.\n"); closesocket(clientSocket); closesocket(serverSocket); WSACleanup(); return 1; } printf("Client connected from: %s\n", clientIP); // 将新的客户端套接字添加到数组中 for (int i = 0; i < MAX_CLIENTS; ++i) { if (clientSockets[i] == INVALID_SOCKET) { clientSockets[i] = clientSocket; break; } } // 向每个客户端发送消息 for (int i = 0; i < MAX_CLIENTS; ++i) { if (clientSockets[i] != INVALID_SOCKET) { if (send(clientSockets[i], message, strlen(message), 0) == SOCKET_ERROR) { printf("Failed to send message to client.\n"); closesocket(clientSockets[i]); clientSockets[i] = INVALID_SOCKET; } } } } // 关闭套接字和清理Winsock for (int i = 0; i < MAX_CLIENTS; ++i) { if (clientSockets[i] != INVALID_SOCKET) { closesocket(clientSockets[i]); } } closesocket(serverSocket); WSACleanup(); return 0; } ``` 在代码中,服务器创建了一个监听套接字,并等待客户端的连接。一旦有客户端连接成功,accept函数将返回一个新的套接字用于与客户端进行通信。然后,将新的客户端套接字添加到一个数组中,以便在发送消息时能够迭代所有客户端。使用循环遍历数组中的每个客户端套接字,并使用send函数向每个客户端发送指定的消息。请注意,此示例仅适用于TCP套接字连接,并且最多支持10个客户端连接。你可以根据需要调整MAX_CLIENTS的值。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值