Win32 socket通信

server
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")

#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"

int __cdecl main(void)
{
	WSADATA wsaData;
	SOCKET ListenSocket = INVALID_SOCKET; //监听套接字
	SOCKET	ClientSocket = INVALID_SOCKET; //客户端套接字
	struct addrinfo *result = NULL,hints;
	char recvbuf[DEFAULT_BUFLEN] = { 0 };

	int iResult, iSendResult;
	int recvbuflen = DEFAULT_BUFLEN;


	// Initialize Winsock 初始化
	iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (iResult != 0) {
		printf("WSAStartup failed: %d\n", iResult);
		return 1;
	}

	ZeroMemory(&hints, sizeof(hints));
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	hints.ai_flags = AI_PASSIVE;

	// Resolve the server address and port
	//getaddrinfo函数能够处理名字到地址以及服务到端口的转换,
	/*
	int getaddrinfo(const char *hostname, const char *service, const struct addrinfo *hints, struct addrinfo **result);
hostname: 一个主机名或者地址串(IPv4的点分十进制串或者IPv6的16进制串)。
service: 服务名,可以是十进制的端口号,也可以是已定义的服务名称,如ftp、http等。
hints: 可以是一个空指针,也可以是指向某个addrinfo结构体的指针。调用者在这个结构中填入关于期望返回的信息类型的暗示。
例如,如果指定的服务既支持TCP也支持UDP,那么调用者可以把hints结构中的ai_socktype成员设置成SOCK_DGRAM,
使得返回的仅仅是适用于数据报套接口的信息。
result: 函数通过result指针参数返回一个指向addrinfo结构体链表的指针。
	*/
	iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);//DEFAULT_PORT=27015 
	if (iResult != 0) {
		printf("getaddrinfo failed: %d\n", iResult);
		WSACleanup();
		system("pause");
		return 1;
	}

	// Create a SOCKET for connecting to server
	ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
	if (ListenSocket == INVALID_SOCKET) {
		printf("socket failed: %ld\n", WSAGetLastError());
		freeaddrinfo(result);
		WSACleanup();
		system("pause");
		return 1;
	}

	// Setup the TCP listening socket
	iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
	if (iResult == SOCKET_ERROR) {
		printf("bind failed: %d\n", WSAGetLastError());
		freeaddrinfo(result);
		closesocket(ListenSocket);
		WSACleanup();
		system("pause");
		return 1;
	}

	freeaddrinfo(result);

	iResult = listen(ListenSocket, SOMAXCONN);
	if (iResult == SOCKET_ERROR) {
		printf("listen failed: %d\n", WSAGetLastError());
		closesocket(ListenSocket);
		WSACleanup();
		system("pause");
		return 1;
	}

	// Accept a client socket
	ClientSocket = accept(ListenSocket, NULL, NULL);
	if (ClientSocket == INVALID_SOCKET) {
		printf("accept failed: %d\n", WSAGetLastError());
		closesocket(ListenSocket);
		WSACleanup();
		system("pause");
		return 1;
	}

	// No longer need server socket
	closesocket(ListenSocket);

	// Receive until the peer shuts down the connection
	do {
		iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
		if (iResult > 0) 
		{
			printf("Bytes received: %d,  %s\n", iResult,recvbuf);
			// Echo the buffer back to the sender
			iSendResult = send(ClientSocket, recvbuf, iResult, 0);
			if (iSendResult == SOCKET_ERROR) {
				printf("send failed: %d\n", WSAGetLastError());
				closesocket(ClientSocket);
				WSACleanup();
				system("pause");
				return 1;
			}
			printf("Bytes sent: %d\n", iSendResult);
		}
		else if (iResult == 0)
		{
			printf("Connection closing...\n");
		}
		else
		{
			printf("recv failed: %d\n", WSAGetLastError());
			closesocket(ClientSocket);
			WSACleanup();
			system("pause");
			return 1;
		}

	} while (iResult > 0);

	// shutdown the connection since we're done
	iResult = shutdown(ClientSocket, SD_SEND);
	if (iResult == SOCKET_ERROR) {
		printf("shutdown failed: %d\n", WSAGetLastError());
		closesocket(ClientSocket);
		WSACleanup();
		system("pause");
		return 1;
	}

	// cleanup
	closesocket(ClientSocket);
	WSACleanup();
	system("pause");
	return 0;
}


#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")

#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
/*
在C或C++程序中,main(int argc, char **argv) 是程序的主入口点。这个函数签名中的参数 argc 和 argv 用于从命令行接收参数。
argc(Argument Count):这是一个整数,表示传递给程序的命令行参数的数量。它至少为1,因为程序自身的名称总是作为第一个参数传递。
argv(Argument Vector):这是一个指向字符指针数组的指针,数组中的每个元素都是指向一个C风格字符串的指针。
这些字符串就是传递给程序的命令行参数。argv[0] 通常是程序的名称,argv[1] 是第一个命令行参数,argv[2] 是第二个命令行参数,以此类推。

*/
int __cdecl main(int argc, char **argv)
{
	argc = 2;
	
	printf("argc=%d\n", argc);
	printf("argv[0]=%s\n", argv[0]);   //可执行程序的名字


	WSADATA wsaData;
	SOCKET ConnectSocket = INVALID_SOCKET;
	struct addrinfo *result = NULL,*ptr = NULL,hints;
	const char *sendbuf = "this is a test";
	char recvbuf[DEFAULT_BUFLEN];
	int iResult;
	int recvbuflen = DEFAULT_BUFLEN;

	// Validate the parameters
	if (argc != 2) {
		printf("usage: %s server-name\n", argv[0]);
		system("pause");
		return 1;
	}

	// Initialize Winsock
	iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (iResult != 0) {
		printf("WSAStartup failed: %d\n", iResult);
		system("pause");
		return 1;
	}

	ZeroMemory(&hints, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	// Resolve the server address and port DEFAULT_PORT=27015
	iResult = getaddrinfo("localhost", DEFAULT_PORT, &hints, &result);
	if (iResult != 0) {
		printf("getaddrinfo failed: %d\n", iResult);
		WSACleanup();
		system("pause");
		return 1;
	}

	// Attempt to connect to an address until one succeeds
	for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {

		// Create a SOCKET for connecting to server
		ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
			ptr->ai_protocol);
		if (ConnectSocket == INVALID_SOCKET) {
			printf("Error at socket(): %ld\n", WSAGetLastError());
			freeaddrinfo(result);
			WSACleanup();
			system("pause");
			return 1;
		}

		// Connect to server.
		iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
		if (iResult == SOCKET_ERROR) {
			closesocket(ConnectSocket);
			ConnectSocket = INVALID_SOCKET;
			continue;
		}
		break;
	}

	freeaddrinfo(result);

	if (ConnectSocket == INVALID_SOCKET) {
		printf("Unable to connect to server!\n");
		WSACleanup();
		system("pause");
		return 1;
	}

	// Send an initial buffer
	iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
	if (iResult == SOCKET_ERROR) {
		printf("send failed: %d\n", WSAGetLastError());
		closesocket(ConnectSocket);
		WSACleanup();
		system("pause");
		return 1;
	}

	printf("Bytes Sent: %ld\n", iResult);

	// shutdown the connection since no more data will be sent
	iResult = shutdown(ConnectSocket, SD_SEND);
	if (iResult == SOCKET_ERROR) {
		printf("shutdown failed: %d\n", WSAGetLastError());
		closesocket(ConnectSocket);
		WSACleanup();
		system("pause");
		return 1;
	}

	// Receive until the peer closes the connection
	do {

		iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
		if (iResult > 0)
			printf("Bytes received: %d\n", iResult);
		else if (iResult == 0)
			printf("Connection closed\n");
		else
			printf("recv failed: %d\n", WSAGetLastError());

	} while (iResult > 0);

	// cleanup
	closesocket(ConnectSocket);
	WSACleanup();
	system("pause");
	return 0;
}


在Qt中,可以使用QTcpSocket和QTcpServer类来实现Windows Socket通信。下面是一个简单的示例代码: ```cpp // 创建socket server QTcpServer *server = new QTcpServer(this); connect(server, SIGNAL(newConnection()), this, SLOT(onNewConnection())); if (!server->listen(QHostAddress::Any, 1234)) { qDebug() << "Error: Failed to start server"; } // 新连接处理 void MyServer::onNewConnection() { QTcpSocket *socket = server->nextPendingConnection(); connect(socket, SIGNAL(readyRead()), this, SLOT(onReadyRead())); connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater())); } // 读取数据 void MyServer::onReadyRead() { QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender()); if (!socket) { return; } QByteArray data = socket->readAll(); // 处理数据 // ... } ``` 这里创建了一个QTcpServer对象,并监听所有的IP地址和端口号为1234的连接请求。当有新的连接请求时,会触发newConnection信号,并在onNewConnection函数中创建一个QTcpSocket对象,并连接readyRead信号和disconnected信号。当数据准备好时,会触发readyRead信号,并在onReadyRead函数中读取数据并进行处理。 在客户端,可以使用QTcpSocket类来连接服务器并发送数据。示例代码如下: ```cpp QTcpSocket *socket = new QTcpSocket(this); socket->connectToHost("127.0.0.1", 1234); if (socket->waitForConnected()) { // 连接成功 socket->write("Hello World"); socket->flush(); } socket->close(); ``` 这里创建了一个QTcpSocket对象,并连接到IP地址为127.0.0.1,端口号为1234的服务器。如果连接成功,则发送一个字符串“Hello World”。注意,Qt中的Socket通信是异步的,因此需要等待连接成功后再发送数据。最后需要关闭socket连接。 以上是一个简单的示例,实际使用中需要根据具体需求进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值