socket通信客户端发送的数据,服务器端只能收到空格后面的数据,这是怎么回事??

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了socket通信客户端发送的数据,服务器端只能收到空格后面的数据,这是怎么回事??相关的知识,希望对你有一定的参考价值。

贴不上代码,好心童鞋请留下QQ~~

参考技术A 其实这一切就看你代码是怎么写的,如果你写成客户端在一直等待服务器端的数据,那当然,服务器端如果没有发送任何消息,那么客户端就会卡在这段代码上,一直等待服务器端等信息,直到服务器关闭或者发送来信息,得到的值也不会是-1,除非服务器端发送的数据就是-1。相反,你的代码写成在客户端与服务器端在相连接后,服务器端一直等待客户端的信息,客户端如果不发送信息的话,服务器端就会卡在这行代码上,不往下运行直到客户端关闭或者客户端发送来命令。
这种情况会导致服务器或者客户端处于一直等待的情况,两边接收的值不一样,发送边发送的是Int型的,接收边接收的是Long型的,两边数据类型不匹配,这边短另一边长,会导致接收端一直接收
所以,你如果想写一个socket程序,建议你用多线程,网上有书,你可以参考参考本回答被提问者和网友采纳

24UDP通信

使用Qt提供的QUdpSocket进行UDP通信。在UDP方式下,客户端并不与服务器建立连接,它只负责调用发送函数向服务器发送数据。类似的服务器也不从客户端接收连接,只负责调用接收函数,等待来自客户端的数据的到达。

技术分享图片

解析:UDP无需确认对方是否在线,是否能收到。因此服务端也不需要设置监听套接字。双发只需通信套接字即可。Socket绑定指定端口号,其他客户端可以通过该端口号直接进行通信。如:服务端bind(888),而不需要绑定888,也可以直接向服务端发出信息,但是服务端无法向客户端回复(因为不知道客户端端口)。对方发出数据,立即触发信号readyRead,再利用readDatagram接收信息,writeDatagram进行发送信息。

 

 

在UDP通信中,服务器端和客户端的概念已经显得有些淡化,两部分做的工作都大致相同:

1.创建套接字

2.绑定套接字,在UDP中如果需要接收数据则需要对套接字进行绑定,只发送数据则不需要对套接字进行绑定。通过调用bind()函数将套接字绑定到指定端口上。

3.接收或者发送数据

接收数据:使用readDatagram()接收数据,函数声明如下:

qint64   readDatagram(char * data, qint64 maxSize,

QHostAddress * address = 0, quint16 * port = 0)

参数:

?   data: 接收数据的缓存地址

?   maxSize: 缓存接收的最大字节数

?   address: 数据发送方的地址(一般使用提供的默认值)

?   port: 数据发送方的端口号(一般使用提供的默认值)

使用pendingDatagramSize()可以获取到将要接收的数据的大小,根据该函数返回值来准备对应大小的内存空间存放将要接收的数据。

发送数据: 使用writeDatagram()函数发送数据,函数声明如下:

qint64   writeDatagram(const QByteArray & datagram,

const QHostAddress & host, quint16 port)

参数:

?   datagram:要发送的字符串

?   host:数据接收方的地址

?   port:数据接收方的端口号

 

 

TCP/IP 和 UDP的区别

 

TCP/IP

UDP

是否连接

面向连接

无连接

传输方式

基于流

基于数据报

传输可靠性

可靠

不可靠

传输效率

效率低

效率高

能否广播

不能

说白了,TCP就是打电话,UDP就是发短信,TCP要确认对方在线并能完整接收,再做出回应。UDP不管对方是否在线,只需最快速率发送给对方,不管对方是否能接收。

 

 

 

服务端

UdpServer.h

#include "udpcilent.h"

#include "ui_udpcilent.h"

 

UdpCilent::UdpCilent(QWidget *parent) :

    QWidget(parent),

    ui(new Ui::UdpCilent)

{

    ui->setupUi(this);

    this->setWindowTitle("服务端端口:8888");

 

    ui->Ip->setText("127.0.0.1");

    ui->Port->setText("888");

 

    m_Client=new QUdpSocket(this);

    //绑定端口号

    m_Client->bind(8888);

 

    //通信

    connect(m_Client,&QUdpSocket::readyRead,

            [=]()

            {

                char pBuf[1024]={0};

                QHostAddress peerIP;

                quint16 port;

                //读取对方的信息,端口,IP

                qint64 size=m_Client->readDatagram(pBuf,1024,&peerIP,&port);

                //显示在信息框

                if(size!=-1)

                {

                    QString strTemp=QString("[%1:%2]:%3").arg(peerIP.toString()).arg(port).arg(pBuf);

                    ui->textEdit_2->setText(strTemp);

                }

            }

    );

 

}

 

UdpCilent::~UdpCilent()

{

    delete ui;

    delete m_Client;

    m_Client=NULL;

}

 

void UdpCilent::on_pushButton_clicked()

{

    //获取要发送的信息,设置对方的IP,端口号

    QString strSend=ui->textEdit->toPlainText();

    QString peerIP=ui->Ip->text();

    quint16 port=ui->Port->text().toInt();

    //发送

    m_Client->writeDatagram(strSend.toUtf8(),(QHostAddress)peerIP,port);

 

}

 

void UdpCilent::on_pushButton_2_clicked()

{

    m_Client->close();

}

 

UdpServer.cpp

#include "UdpServer.h"

#include "ui_widget.h"

 

#include <QHostAddress>

#include <QDebug>

 

Widget::Widget(QWidget *parent) :

    QWidget(parent),

    ui(new Ui::Widget)

{

    ui->setupUi(this);

    this->setWindowTitle("服务器端口:888");

 

    ui->Ip->setText("127.0.0.1");

    ui->Port->setText("8888");

 

    //分配空间,指定父对象

    m_Server=new QUdpSocket(this);

 

    //绑定端口号

    m_Server->bind(888);

 

    //通信

    connect(m_Server,&QUdpSocket::readyRead,

            [=]()

            {

                char pBuf[1024]={0};

                QHostAddress peerIP;

                quint16 port;

                //读取对方的信息,端口,IP

                qint64 size=m_Server->readDatagram(pBuf,sizeof(pBuf),&peerIP,&port);

                //显示在信息框

                if(size!=-1)

                {

                    QString strTemp=QString("[%1:%2]:%3").arg(peerIP.toString()).arg(port).arg(pBuf);

                    ui->textEdit_2->append(strTemp);

                }

            }

    );

}

 

Widget::~Widget()

{

    delete ui;

    delete m_Server;

    m_Server=NULL;

}

 

void Widget::on_pushButton_clicked()

{

    //获取要发送的信息,设置对方的IP,端口号

    QString strSend=ui->textEdit->toPlainText();

    QString peerIP=ui->Ip->text();

    quint16 port=ui->Port->text().toInt();

    //发送

    m_Server->writeDatagram(strSend.toUtf8(),QHostAddress(peerIP),port);

 

}

 

void Widget::on_pushButton_2_clicked()

{

    m_Server->close();

}

 

 

同一程序添加两个窗口,且有设计器。新建一个文件,但不是C++类文件,而是QT且带有界面类的,最后在main中使用show()直接显示。如下图:

技术分享图片

 

 

 

客户端

UdpServer.h

#ifndef UDPSERVER_H

#define UDPSERVER_H

 

#include <QWidget>

#include <QUdpSocket>

 

namespace Ui {

class Widget;

}

 

class Widget : public QWidget

{

    Q_OBJECT

 

public:

    explicit Widget(QWidget *parent = 0);

    ~Widget();

 

private slots:

    void on_pushButton_clicked();       //发送

    void on_pushButton_2_clicked();     //关闭通信(其实没用)

 

private:

    Ui::Widget *ui;

 

    QUdpSocket *m_Server;   //服务器的通信套接字

};

 

#endif // UDPSERVER_H

 

udpcilent.cpp

#include "udpcilent.h"

#include "ui_udpcilent.h"

 

UdpCilent::UdpCilent(QWidget *parent) :

    QWidget(parent),

    ui(new Ui::UdpCilent)

{

    ui->setupUi(this);

    this->setWindowTitle("服务端端口:8888");

 

    ui->Ip->setText("127.0.0.1");

    ui->Port->setText("888");

 

    m_Client=new QUdpSocket(this);

    //绑定端口号

    m_Client->bind(8888);

 

    //通信

    connect(m_Client,&QUdpSocket::readyRead,

            [=]()

            {

                char pBuf[1024]={0};

                QHostAddress peerIP;

                quint16 port;

                //读取对方的信息,端口,IP

                qint64 size=m_Client->readDatagram(pBuf,1024,&peerIP,&port);

                //显示在信息框

                if(size!=-1)

                {

                    QString strTemp=QString("[%1:%2]:%3").arg(peerIP.toString()).arg(port).arg(pBuf);

                    ui->textEdit_2->setText(strTemp);

                }

            }

    );

 

}

 

UdpCilent::~UdpCilent()

{

    delete ui;

    delete m_Client;

    m_Client=NULL;

}

 

void UdpCilent::on_pushButton_clicked()

{

    //获取要发送的信息,设置对方的IP,端口号

    QString strSend=ui->textEdit->toPlainText();

    QString peerIP=ui->Ip->text();

    quint16 port=ui->Port->text().toInt();

    //发送

    m_Client->writeDatagram(strSend.toUtf8(),(QHostAddress)peerIP,port);

 

}

 

void UdpCilent::on_pushButton_2_clicked()

{

    m_Client->close();

}

 

 

main.cpp

#include "UdpServer.h"

#include <QApplication>

#include <udpcilent.h>

 

int main(int argc, char *argv[])

{

    QApplication a(argc, argv);

    Widget w;

    w.show();

 

    UdpCilent u;

    u.show();

    return a.exec();

}

 

程序结果图:

技术分享图片

 

以上是关于socket通信客户端发送的数据,服务器端只能收到空格后面的数据,这是怎么回事??的主要内容,如果未能解决你的问题,请参考以下文章

TCP socket 通信的流程?

Java 实例演示-ServerSocket 和 Socket 通信实例

TCP网络通信编程(字符流)-Socket应用

TCP网络通信编程(字符流)-Socket应用

网络编程 TCP协议:三次握手,四次回收,反馈机制 socket套接字通信 粘包问题与解决方法

socket编程中的接收数据丢失问题