深入探究connect函数

connect()用于建立与指定socket的连接。
头文件: #include <sys/socket.h>
函数原型: int connect(int s, const struct sockaddr * name, int namelen);
参数:
s:标识一个未连接socket
name:指向要连接套接字的 sockaddr结构体的指针
namelen:sockaddr结构体的字节长度

客户端和服务端的连接方式如下:
客户端---------->(SYN)服务器端
服务器端----------->(ACK,SYN)客户端
客户端----------->(SYN)服务器端
在建立好连接后,使用send/recv来发送或接收数据不需要指定地址,但一个套接字只能connect一次。

如果客户端要和其他的服务器端通信,必须再建立一个流式套接字,重新连接。

QT_connect函数:
原型:bool QObject::connect(const QObject* sender,const char * signal,const QObject * receiver,const char * member)[static]
connect(sender,SIGNAL(signal()),receiver,SLOT(slot()));
这里用到了两个宏:SIGNAL() 和SLOT();这两个宏最后是得到一个const char*类型。
connect调用后,emit() signal会直接调用之前connect过的 SLOT函数。

SIGNAL()宏和SLOT()宏中的函数的参数一定要严格一致。

在QObject.cpp文件中可以找到connect的实现代码,下面是去除了debug代码的connect实现。


  1. bool QObject::connect(const QObject *sender, const char *signal,  
  2.                       const QObject *receiver, const char *method,  
  3.                       Qt::ConnectionType type)  
  4. {  
  5.     {  
  6.         const void *cbdata[] = { sender, signal, receiver, method, &type };  
  7.         if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))  
  8.             return true;  
  9.     }  
  10.   
  11.     if (sender == 0 || receiver == 0 || signal == 0 || method == 0) {  
  12.         qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",  
  13.                  sender ? sender->metaObject()->className() : "(null)",  
  14.                  (signal && *signal) ? signal+1 : "(null)",  
  15.                  receiver ? receiver->metaObject()->className() : "(null)",  
  16.                  (method && *method) ? method+1 : "(null)");  
  17.         return false;  
  18.     }  
  19.     QByteArray tmp_signal_name;  
  20.   
  21.     if (!check_signal_macro(sender, signal, "connect""bind"))  
  22.         return false;  
  23.     const QMetaObject *smeta = sender->metaObject();  
  24.     const char *signal_arg = signal;  
  25.     ++signal; //skip code  
  26.     int signal_index = smeta->indexOfSignal(signal);  
  27.     if (signal_index < 0) {  
  28.         // check for normalized signatures  
  29.         tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);  
  30.         signal = tmp_signal_name.constData() + 1;  
  31.   
  32.         signal_index = smeta->indexOfSignal(signal);  
  33.         if (signal_index < 0) {  
  34.             err_method_notfound(sender, signal_arg, "connect");  
  35.             err_info_about_objects("connect", sender, receiver);  
  36.             return false;  
  37.         }  
  38.     }  
  39.   
  40.     QByteArray tmp_method_name;  
  41.     int membcode = extract_code(method);  
  42.   
  43.     if (!check_method_code(membcode, receiver, method, "connect"))  
  44.         return false;  
  45.     const char *method_arg = method;  
  46.     ++method; // skip code  
  47.   
  48.     const QMetaObject *rmeta = receiver->metaObject();  
  49.     int method_index = -1;  
  50.     switch (membcode) {  
  51.     case QSLOT_CODE:  
  52.         method_index = rmeta->indexOfSlot(method);  
  53.         break;  
  54.     case QSIGNAL_CODE:  
  55.         method_index = rmeta->indexOfSignal(method);  
  56.         break;  
  57.     }  
  58.     if (method_index < 0) {  
  59.         // check for normalized methods  
  60.         tmp_method_name = QMetaObject::normalizedSignature(method);  
  61.         method = tmp_method_name.constData();  
  62.         switch (membcode) {  
  63.         case QSLOT_CODE:  
  64.             method_index = rmeta->indexOfSlot(method);  
  65.             break;  
  66.         case QSIGNAL_CODE:  
  67.             method_index = rmeta->indexOfSignal(method);  
  68.             break;  
  69.         }  
  70.     }  
  71.   
  72.     if (method_index < 0) {  
  73.         err_method_notfound(receiver, method_arg, "connect");  
  74.         err_info_about_objects("connect", sender, receiver);  
  75.         return false;  
  76.     }  
  77.     if (!QMetaObject::checkConnectArgs(signal, method)) {  
  78.         qWarning("QObject::connect: Incompatible sender/receiver arguments"  
  79.                  "\n        %s::%s --> %s::%s",  
  80.                  sender->metaObject()->className(), signal,  
  81.                  receiver->metaObject()->className(), method);  
  82.         return false;  
  83.     }  
  84.   
  85.     int *types = 0;  
  86.     if ((type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)  
  87.             && !(types = queuedConnectionTypes(smeta->method(signal_index).parameterTypes())))  
  88.         return false;  
  89.   
  90.     QMetaObject::connect(sender, signal_index, receiver, method_index, type, types);  
  91.     const_cast<QObject*>(sender)->connectNotify(signal - 1);  
  92.     return true;  
  93. }  


判断连接是否已经建立:

  1. const void *cbdata[] = { sender, signal, receiver, method, &type };  
  2. if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))  
  3.       return true


猜你喜欢

转载自blog.csdn.net/sakicc/article/details/73006316