WSAStartup函数编程示例--支持断开后人工重连

本文介绍如何使用QT和Visual Studio 2017开发环境结合Winsock2函数库,实现一个简单的TCP客户端应用程序。客户端通过两个主要组件——ClientTCP和ClientThread——与服务器交互,展示接收到的数据。

windows提供了 winsock2函数库,支持 tcp编程。本博客简单演示qt 结合 vs2017,实现tcp客户端。

代码分为两个文件:ClientTCP和ClientThread。clientTCP只提供一个Qwidget的窗体,用于显示从tcp服务器端发来的数据;clientThread继承自QThread,周而复始的接收从服务器发来的数据,然后交给ClientTCP显示。tcp socket的创建也由ClientThread完成。

代码:

main.cpp

#include "ClientTCP.h"
#include <QtWidgets/QApplication>
#include "ClientThread.h"

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	ClientThread thrd;
	ClientTCP w;
	w.show();
	return a.exec();
}

ClientTCP.H

#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_ClientTCP.h"

class ClientTCP : public QMainWindow
{
	Q_OBJECT

public:
	ClientTCP(QWidget *parent = Q_NULLPTR);
	~ClientTCP();

	static ClientTCP *		pGetInstance(void);
	void					setMsg(char *);
private:
	Ui::ClientTCPClass ui;
private slots:
	void					OnClickConnect(void);
};

ClientCP.cpp

#include "ClientTCP.h"
#include "ClientThread.h"

ClientTCP *		pInstance = NULL;

ClientTCP::ClientTCP(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);

	pInstance = this;
	connect(ui.BtnConnect, SIGNAL(clicked()), this, SLOT(OnClickConnect()));
}

ClientTCP::~ClientTCP()
{

}


ClientTCP * ClientTCP::pGetInstance(void)
{
	return pInstance;
}

void ClientTCP::setMsg(char * pMsg)
{
	ui.label->setText(QString(pMsg));
}

void ClientTCP::OnClickConnect(void)
{
	ClientThread * pThread = ClientThread::pGetInstance();
	pThread->start();
}

clientThread.h

#pragma once
#include <winsock.h>
#include <QThread>


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

class ClientThread : public QThread
{
public:
	ClientThread();
	~ClientThread();

	static ClientThread * pGetInstance();
	SOCKET			m_socket;
	
protected:
	void			run();
};

clientThread.cpp

#include "ClientThread.h"
#include "ClientTCP.h"

int MFCconnect(SOCKET skt, const sockaddr * pAddr, int iLen)
{
	return connect(skt, pAddr, iLen);
}

ClientThread * pInstance = NULL;
ClientThread::ClientThread() : QThread()
{
	pInstance = this;
}

ClientThread::~ClientThread()
{
	terminate();
}

void ClientThread::run()
{
	WSAData wsaData;
	int iRet = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (0 == iRet)
	{
		m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
		if (INVALID_SOCKET != m_socket)
		{
			sockaddr_in saServer;
			saServer.sin_family = AF_INET; //地址家族  
			saServer.sin_port = htons(5050); //注意转化为网络节序  
			saServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
			if (SOCKET_ERROR != MFCconnect(m_socket, (const sockaddr  *)&saServer, (int)sizeof(saServer)))
			{
				ClientTCP * pDlg = ClientTCP::pGetInstance();
				while (true)
				{
					char szBuf[256] = { 0 };
					short sRet = recv(m_socket, szBuf, 250, 0);
					if (SOCKET_ERROR == sRet)
					{
						int nError = WSAGetLastError();
				
						break;
					}
					else if (0 == sRet)//链接断开
					{
						int nError = WSAGetLastError();

						break;
					}
					else
					{
						pDlg->setMsg(szBuf);
					}
				}

				WSACleanup();
			}
		}
	}
}

ClientThread * ClientThread::pGetInstance()
{
	return pInstance;
}

假如tcp服务器与客户端断开,clienthread将自动跳出while循环。用户再次点击"connect"按钮,会重新建立链接。

效果:

1)启动网络助手,设置为服务器模式,且端口设为5050,IP为127.0.0.1

2)启动自己的客户端程序,点击connect按钮

3)点击后,你会发现网络助手的界面浮现出客户端的信息

4)点击发送按钮,网络助手输入框中的字符就显示再客户端的界面上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值