|
搜索了qt-interest,发现对如何在qt环境下进行udp编程的提问很多,但大多没有回复.其实qt本身已经封装了的QSocket类提供了
高级的SOCKET支持,为编写因特网环境下的C/S程序提供了极大的方便,但QSocket类仅仅支持Tcp/Ip方式的通讯,不支持udp方式的
通讯. 所以编写Udp方式的程序的话,就必须使用qt封装的较低级的QSocketDevice类.同时也希望本文能够带你走进qt编程的殿堂.
首先用qtdesigner完成程序界面的设计.
保存为ChatDialog,编译一下,将会生成
chatdialog.cpp
moc_chatdialogimpl.cpp
moc_chatdialog.cpp
以及几个头文件.所自动建立的类名为ChatDialogBase.
其次,建立一个新类:chat,继承于ChatDialogBase类.生成的头文件如下:
[code:1]
//chat.h
#include <qvariant.h>
#include <qsocketdevice.h>
#include <qsocketnotifier.h>
#include <qlineedit.h>
#include <qmultilineedit.h>
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include "chatdialog.h"
class chat: public ChatDialogBase
{
Q_OBJECT
public:
void ListenOnPort(int Port);
chat(QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 );
virtual ~chat();
QSocketNotifier *SocketNotifier;
QSocketDevice *UReceiveSocket; //接收
QSocketDevice *USendSocket; //发送
private:
int ListenPort;
private slots:
void OnIncommingData();
void OnReturnPressed();
};
//chat.cpp
#include "chat.h"
#include <qtextcodec.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
chat::chat(QWidget* parent, const char* name, bool modal, WFlags f1)
: ChatDialogBase( parent, name, modal, f1 )
{
USendSocket = new QSocketDevice(QSocketDevice::Datagram);
UReceiveSocket = new QSocketDevice(QSocketDevice::Datagram);
ListenOnPort(2020);
//用qt的信号和槽机制连接return事件到槽OnReturnPressed()
connect(MessageEdit,SIGNAL(returnPressed()),this,SLOT(OnReturnPressed()));
}
chat::~chat()
{
delete SocketNotifier;
delete UReceiveSocket;
delete USendSocket;
}
void chat::OnReturnPressed() //发送消息
{
char *DataToSend;
QString StringToSend, PortString;
QHostAddress HostAddress;
int PortNumber;
bool TestBool;
int BytesSent;
//============
StringToSend = MessageEdit->text();
QTextCodec *codec=QTextCodec::codecForName("GBK");
//转换编码
QCString chinese_string=codec->fromUnicode(StringToSend);//用QCString来存储返回的多字节编码
DataToSend = (char *)malloc(chinese_string.length()+ 1);
strcpy(DataToSend,(const char *)chinese_string);
DataToSend[chinese_string.length()] = '\0';
/*DataToSend = (char *)malloc(StringToSend.length()+ 1);//为了支持中文发送而屏蔽
strcpy(DataToSend,(const char *)StringToSend);
DataToSend[StringToSend.length()] = '\0';*/
HostAddress.setAddress(AddressEdit->text());
PortString = PortEdit->text();
PortNumber = PortString.toInt(&TestBool,10);
if(ListenPort != PortNumber)
{
UReceiveSocket->close();
ListenOnPort(PortNumber);
}
// BytesSent =USendSocket->writeBlock(DataToSend,StringToSend.length(),HostAddress,PortNumber);
BytesSent =USendSocket->writeBlock(DataToSend,chinese_string.length(),HostAddress,PortNumber);
printf("-> %s\n",DataToSend);
free(DataToSend);
StringToSend = "-> "+StringToSend;
MessageHistory->append(StringToSend);
}
void chat::OnIncommingData() //udp服务器端接收消息
{
int ByteCount,ReadCount;
char *IncommingChar;
QString IncommingString;
QHostAddress PeerAddress;
ByteCount = UReceiveSocket->bytesAvailable();
IncommingChar = (char *)malloc(ByteCount+1);
ReadCount = UReceiveSocket->readBlock(IncommingChar,ByteCount*2);
IncommingChar[ReadCount] = '\0';
IncommingString = "<- ";
IncommingString += IncommingChar;
//======转换编码为unicode,qt默认的是unicode编码
QTextCodec* codec = QTextCodec::codecForName("GBK");
QString gbk_string = codec->toUnicode(IncommingString);
MessageHistory->append(gbk_string);
//==========================================
// MessageHistory->append(IncommingString);
printf("<- %s\n",IncommingChar);
free(IncommingChar);
// Set the IP address to the one that just sent me a message
PeerAddress = UReceiveSocket->peerAddress();
AddressEdit->setText(PeerAddress.toString());
}
void chat::ListenOnPort(int Port)
{
QHostAddress MyAddress;
QString FakeAddress;
ListenPort = Port;
FakeAddress = "127.0.0.1";
MyAddress.setAddress(FakeAddress);
UReceiveSocket->bind(MyAddress,ListenPort);
//以非阻塞方式建立侦听
SocketNotifier = new QSocketNotifier(UReceiveSocket->socket(),QSocketNotifier::Read,0,"SocketNotifier");
//触发OnIncommingData事件
connect(SocketNotifier,SIGNAL(activated(int)),SLOT(OnIncommingData()));
}[/code:1] |
|