• 331阅读
  • 13回复

[提问]使用QTcpSocket对象write出现段错误 [复制链接]

上一主题 下一主题
离线介农酥
 

只看楼主 倒序阅读 楼主  发表于: 05-12
回复本帖可获得5RMB金钱奖励!
每人最多可获奖1次,奖池剩余5RMB金钱 (中奖几率10%)
程序(相关部分):

Server::Server(QObject *parent)
    : QTcpServer(parent)
{
    connect(this, SIGNAL(newConnection()),
            this, SLOT(addSocketToList()));
}

void Server::addSocketToList()
{  
    qDebug() << list.length();  //打印QList<QTcpSocket *>的长度,开始为0
    list.append(nextPendingConnection()); //将新来的Socket添加到链表
    qDebug() << list.length(); //长度增加一个,为1
    QTcpSocket *socketFromList = list.at(0); //从链表中取出Socket
    socketFromList->write("abc"); //这步出现段错,只要操作socketFromList就段错误
    socketFromList->waitForBytesWritten();

}

备注:Server类继承QTcpServer。
结果:


难道说nextPendingConnection返回的对象指针不能在QTcpServer对象中使用?

其实我就是做一个聊天室的程序,,我把客户A的内容发给服务器,服务器发给其他客户端,比如B、C、D……(都在线程里),一两天都没想到办法,我好不容易网上看到有人把到来socket保存的QList中,然后一个个取出,才通过它们发到对应的客户端,可以当我write的时候就段错误,我真不知道什么原因(或者大家是怎么实现将客户A的聊天内容发给其他客户端(线程内))?
在线20091001753

只看该作者 1楼 发表于: 05-12
客户端 QTcpSocket ,服务端 QTcpSocket + QTcpServer
相互通讯的是两个 QTcpSocket ,而 QTcpServer 充当的角色是,类似于接待员。
(づ ̄ 3 ̄)づ
离线介农酥

只看该作者 2楼 发表于: 05-13
怎样将一个客户端发给其他客户端
离线介农酥

只看该作者 3楼 发表于: 05-13
回 20091001753 的帖子
20091001753:客户端 QTcpSocket ,服务端 QTcpSocket + QTcpServer
相互通讯的是两个 QTcpSocket ,而 QTcpServer 充当的角色是,类似于接待员。
 (2019-05-12 23:05) 

怎样发给其他客户端
离线angelus

只看该作者 4楼 发表于: 05-13
基本都是这样  中转服务器模式,大差不差,  不过服务器一般用多线程处理,使用[virtual protected] void QTcpServer::incomingConnection(qintptr socketDescriptor) 函数,然后创建一个QHash保存键值对<int,QTcpServer *> 方便进行索引,读写加锁。 根据A发的信息的对象id,取出指针,直接读写

你最好看下你取出的指针对象是否有效!
判断下 bool QAbstractSocket::isValid() const  查看连接是否有效
或者
QAbstractSocket::SocketState QAbstractSocket::state() const
QAbstractSocket::ConnectingState     已连接状态,然后再调用write()


离线介农酥

只看该作者 5楼 发表于: 05-13
回 angelus 的帖子
angelus:基本都是这样  中转服务器模式,大差不差,  不过服务器一般用多线程处理,使用[virtual protected] void QTcpServer::incomingConnection(qintptr socketDescriptor) 函数,然后创建一个QHash保存键值对<int,QTcpServer *> 方便进行索引,读写加锁。  .. (2019-05-13 09:08)

谢谢,我用state不行,只要操作nextPendingConnection返回的QTcpSocket指针对象就段错误,我在想段错误,基本就是访问了非法的内存,难道我返回的QTcpSocket的是NULL。经过验证,打印的地址是QObject(0x0)。
离线介农酥

只看该作者 6楼 发表于: 05-14
终于知道答案了,已在自己电脑上验证。

如果要想nextPendingConnection返回不为空,就不能重写虚函数incomingConnection(),否则就会返回空,所以如果想获得QTcpSocket队列,就无法使用incomingConnection()。且nextPendingConnection()不能连续调用两次,第二次返回空;
离线angelus

只看该作者 7楼 发表于: 05-16
回 介农酥 的帖子
回帖奖励+ 5
介农酥:终于知道答案了,已在自己电脑上验证。
如果要想nextPendingConnection返回不为空,就不能重写虚函数incomingConnection(),否则就会返回空,所以如果想获得QTcpSocket队列,就无法使用incomingConnection()。且nextPendingConnection()不能连续调用两次,第二次返回空; (2019-05-14 16:50) 

重写了incomingConnection()肯定会错啊,因为重写后就不会创建socket,而是只创建一个socket描述符id,用来延后在线程中创建socket 用,net函数返回的socket是不能在分线程中使用的
离线介农酥

只看该作者 8楼 发表于: 05-16
回 angelus 的帖子
angelus:重写了incomingConnection()肯定会错啊,因为重写后就不会创建socket,而是只创建一个socket描述符id,用来延后在线程中创建socket 用,net函数返回的socket是不能在分线程中使用的 (2019-05-16 08:57) 

但是最终的问题还是没有解决,因为返回的对象指针不能在线程中使用,当我在线程中收到线程发过来的内容之后,我需在该线程中遍历其他socket,将内容发给其他客户端,但是却不能。困扰很久,还望高人指点。
离线angelus

只看该作者 9楼 发表于: 05-16
链接:https://pan.baidu.com/s/1jyspf_pfiLHVBSDfFi6TZQ
提取码:uj32


这个是前几年写的一个教学用的程序,里边涉及了一个简单的聊天软件
关于多线程 , 加密 , 群发和定向私聊的功能,很简单
你说的问题,可以在里边找到答案,不懂的可以回帖问我


离线angelus

只看该作者 10楼 发表于: 05-16
回 介农酥 的帖子
介农酥:但是最终的问题还是没有解决,因为返回的对象指针不能在线程中使用,当我在线程中收到线程发过来的内容之后,我需在该线程中遍历其他socket,将内容发给其他客户端,但是却不能。困扰很久,还望高人指点。 (2019-05-16 12:32)

思路其实很简单,把存储用户的socket指针存储到 静态容器中,然后加入锁,读写容器的时候加锁,在线程中是可以访问静态变量的,从中取出指针,然后调用指针中类的方法发送数据就行

容器推荐用QHash进行键值对存储,原则上来说 15万个 值,读的速度大概是查找1万个值,用时1毫秒 , QMap是4毫秒,这种速度,锁在读的时候反而是种累赘,但是写一定是要加锁的!

离线介农酥

只看该作者 11楼 发表于: 05-16
回 angelus 的帖子
angelus:链接:https://pan.baidu.com/s/1jyspf_pfiLHVBSDfFi6TZQ
提取码:uj32
这个是前几年写的一个教学用的程序,里边涉及了一个简单的聊天软件
....... (2019-05-16 13:22) 

离线介农酥

只看该作者 12楼 发表于: 05-16
回 angelus 的帖子
angelus:思路其实很简单,把存储用户的socket指针存储到 静态容器中,然后加入锁,读写容器的时候加锁,在线程中是可以访问静态变量的,从中取出指针,然后调用指针中类的方法发送数据就行
容器推荐用QHash进行键值对存储,原则上来说 15万个 值,读的速度大概是查找1万个值,用时1毫秒  .. (2019-05-16 13:34) 

楼主,交个朋友
离线fsu0413

只看该作者 13楼 发表于: 05-23
重写incomingConnection其实也可以啊
参考Qt的文档,incomingConnection就是给你重写的

void QTcpServer::incomingConnection(qintptr socketDescriptor)
{
#if defined (QTCPSERVER_DEBUG)
    qDebug("QTcpServer::incomingConnection(%i)", socketDescriptor);
#endif

    QTcpSocket *socket = new QTcpSocket(this);
    socket->setSocketDescriptor(socketDescriptor);
    addPendingConnection(socket);
}

照着这个逻辑重写
快速回复
限100 字节
 
上一个 下一个