C++ TCP socket程式設計中的小陷阱(服務端accept 不阻塞 和 客戶端connect 重連失敗)
在編寫一個使用C++ socket實現的TCP服務端與客戶端小軟體時接連碰上2個小陷阱,
終歸是實踐不足,基本功不紮實。
第1個問題: 服務端的accept函式沒有阻塞
程式執行到accept這裡時直接就跳了過去,根本沒停下來。
懷疑過socket的配置是否有錯誤,經過各種除錯,當把socket部分的程式碼從工程中截取出,單獨放到一個空白工程中執行時,一切又都正常了。
證實了socket的配置沒有問題,只能是原工程中的哪個標頭檔案包含後把socket的函式覆蓋了。
又經過了幾次試驗,最終定位到了罪魁禍首竟然是using namespace std
網上查了一下才知道原來這也是個常見問題。因為std的名稱空間裡包含了太多常用的函式名,當全域性使用std名稱空間時,很容易發生函式執行沒有得到預期的效果。
在socket的這個問題中,重要的bind函式被std中的同名函式覆蓋,使得服務端的socket沒有繫結ip地址和商品,自然之後的accept函式也就不能正常阻塞。
對策有2種,
1是把bind函式改為全域性呼叫方式 ::bind(), 擺脫std名稱空間的影響。
2是放棄std名稱空間在全域性範圍內的宣告,改用指定使用函式的方式。 如 using std::cout 或using std::endl
第2個問題:客戶端socket斷開後重連失敗
這是在測試的時候發現的問題。這次的小軟體設計是客戶端在與服務端保持TCP連線的過程中可以隨意向服務端傳送命令。操作結束後可以暫時斷開TCP連線,當有需求時再次連線。
因此客戶端的處理框架是迴圈等待使用者輸入,再根據內容來判斷需要向服務端發起什麼樣的操作請求。
WORD wVersionRequested; WSADATA wsaData; int err; SOCKET sockClient; wVersionRequested = MAKEWORD(1, 1); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { return; } if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); return; } sockClient = socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addrSrv; inet_pton(AF_INET, "127.0.0.1", &addrSrv.sin_addr.s_addr); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(6000); while (1) { char in_buf[40]; string input_command; cin >> in_buf; input_command = in_buf; if (input_command.compare("TCP connect") == 0) { connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); char recvBuf[500]; recv(sockClient, recvBuf, 500, 0); printf("%s\n", recvBuf); } else if (input_command.compare("operation") == 0) { char requst_buf[40] = "operation"; send(sockClient, requst_buf, strlen(requst_buf) + 1, 0); char recvBuf[500]; recv(sockClient, recvBuf, 500, 0); printf("%s\n", recvBuf); } else if (input_command.compare("disconnect") == 0) { char requst_buf[40] = "disconnect"; send(sockClient, requst_buf, strlen(requst_buf) + 1, 0); char recvBuf[500]; recv(sockClient, recvBuf, 500, 0); printf("%s\n", recvBuf); closesocket(sockClient); } }
這樣的客戶端程式碼在啟動後第一次連線服務端時一切都很正常,但在斷開後做再次連線時發生了異常,服務端並沒有收到再連線請求,一直停留在accept阻塞的位置。而客戶端卻能收到socket的資訊反饋,但進一步確認後發現也只能收到返回訊息,需要服務端處理的操作就無法得到服務端的響應。
這個現象就像是客戶端在做二次連線時,連線請求並沒有送到服務端,而只是把客戶端可能會收到的返回訊息作為快取放在socket中,給客戶端造成一種已經再次連線上的假象。
又經過一陣網路搜尋,原來這也是一種常見現象。已經連線過的socket資源不能直接用於再次連線,要麼對它做一次初始化,要麼再次生成一個新的socket資源。作為修改,我選擇了後者。
if (input_command.compare("TCP connect") == 0)
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
return;
}
if (LOBYTE(wsaData.wVersion) != 1 ||
HIBYTE(wsaData.wVersion) != 1) {
WSACleanup();
return;
}
SOCKET sockClient;
sockClient = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addrSrv;
inet_pton(AF_INET, "127.0.0.1", &addrSrv.sin_addr.s_addr);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6000);
connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
char recvBuf[500]; recv(sockClient, recvBuf, 500, 0);
printf("%s\n", recvBuf);
}
把socket的建立程式碼移到發起TCP連線時才執行,保證每次發起連線請求用的都是新的socket,問題得到解決。
相關推薦
C++ TCP socket程式設計中的小陷阱(服務端accept 不阻塞 和 客戶端connect 重連失敗)
在編寫一個使用C++ socket實現的TCP服務端與客戶端小軟體時接連碰上2個小陷阱, 終歸是實踐不足,基本功不紮實。 第1個問題: 服務端的accept函式沒有阻塞 程式執行到accept這裡時直接就跳了過去,根本沒停下來。 懷疑過socket
簡單的TCP協議 socket程式設計(C語言版伺服器和客戶端)
最近由於本人對網路程式設計的喜愛,所以對一點關於TCP協議socket程式設計的總結。由於本人的能力有限,寫的可能過於簡單,只適合初學者,歡迎大牛提出寶貴的意見,本人會感激不盡的。廢話少說了,進入正題。(下面程式碼是基於VC6.0) 下圖
Qt:Qt實現Winsock網路程式設計—TCP服務端和客戶端通訊(多執行緒)
Qt實現Winsock網路程式設計—TCP服務端和客戶端通訊(多執行緒) 前言 感覺Winsock網路程式設計的api其實和Linux下網路程式設計的api非常像,其實和其他程式語言的網路程式設計都差不太多。博主用Qt實現的,當然不想用黑視窗唄,有介面可以看到,由於GUI程式設計
C#程式設計 socket程式設計之tcp伺服器端和客戶端
基於Tcp協議的Socket通訊類似於B/S架構,面向連線,但不同的是伺服器端可以向客戶端主動推送訊息。 使用Tcp協議通訊需要具備以下幾個條件: (1).建立一個套接字(Socket) (2).繫結伺服器端IP地址及埠號--伺服器端 (3).利用Listen()方法開啟監聽--伺服
java socket網路程式設計例項程式碼(含服務端和客戶端)
本程式碼為java socket網路程式設計例項程式碼,包括客戶端和服務端,實現客戶端傳送訊息,服務端接收並反饋訊息。 server.java為服務端程式碼。 client.java為客戶端程式碼。 服務端程式碼server.java: package socket;
Windows C語言 Socket程式設計 server端(伺服器)--初級(多客戶端——初級版)
看過我的簡單版的伺服器程式碼的,會發現那段程式碼同一時間只能和一個客戶端通訊。這樣的程式碼能力很小侷限性很大。今天我來介紹一種多客戶端的伺服器程式碼。當然這段程式碼還是有問題的,至於是什麼問題我會在程式碼後面說清楚。 我的這個多客戶端的程式碼核心思想是多執行緒
Windows C語言 Socket程式設計 client端(客戶端)--斷線重連版
瞭解了最基礎的C語言客戶端的編寫流程,稍稍加以改動即可實現斷線重連。 當伺服器掉線時,客戶端會以固定的頻率不停的重連。 #include <stdio.h> #include <winsock2.h> #pragma comme
Socket程式設計(非同步通訊)(Tcp,Udp)
上一章主要展示了Socket的Tcp\Udp兩種協議下的基本通訊方式,屬於同步通訊。至於一個伺服器對應多個客戶端,或者對應多個請求,我們採用的是多執行緒的方式來解決此問題。然而本章節我們將有更好的方式去實現它:Socket在Tcp\Udp兩種協議下的非同步通訊方式。 基
MFC——socket程式設計(淺出+深度:服務端和客戶端埠問題)
要寫網路程式就必須用Socket,這是程式設計師都知道的。而且,面試的時候,我們也會問對方會不會Socket程式設計?一般來說,很多人都會說,Socket程式設計基本就是listen,accept以及send,write等幾個基本的操作。是的,就跟常見的檔案操作一樣,只要寫過就一定知道。 對於網路程式設計,
C#版 Socket程式設計(最簡單的Socket通訊功能)
示例程式是同步套接字程式,功能很簡單,只是客戶端發給伺服器一條資訊,伺服器向客戶端返回一條資訊;這裡只是一個簡單的示例,是一個最基本的socket程式設計流程,在接下來的文章中,會依次記錄套接字的同步和非同步,以及它們的區別。 下面是示例程式的簡單步驟說明 伺服器端:
我所不知道的TCP Socket程式設計(五)-交換資料、套接字讀寫操作
五:交換資料 已經建立了伺服器和客戶端的連結,現在需要讓它們進行資料交換; 你可以將TCP連線想象成一串連線了本地套接字和遠端套接字的管子,我們可以沿著這個管子傳送和接受資料;
Socket系列(二)基於Socket網路通訊的服務端和客戶端程式設計
Socket系列一主要介紹了Socket的基礎知識、工作原理以及與傳統的http協議的區別。這部分內容的目的是為本文做鋪墊。本文將介紹基於Socket網路通訊的伺服器端和客戶端的程式設計。 一、伺服器端的程式設計 關於Socket伺服器端的
C#Socket程式設計詳解(三)Socket程式設計
三、Socket程式設計1、UDP通訊1.1採用Socket實現UDP1.1.1簡介Socket實現UDP的基本步驟如下:(1)建立一個Socket物件Socket mySocket = new Socket(AddressFamily.InterNetwork,Socket
Linux c實現一個tcp文件服務器和客戶端
repr snippets 功能 stderr strcpy fprintf inet_addr 編寫 create 總體需求:編寫tcp文件服務器和客戶端。客戶端可以上傳和下載文件。 ===========================================
Linux C++ TCP Socket通信實例
內容 set color 分享 int clas 打開 makefile src 環境:Linux 語言:C++ 通信方式:TCP 下面用TCP協議編寫一個簡單的服務器、客戶端,其中服務器端一直監聽本機的6666號端口。如果收到連接請求,將接收請求並接收客戶端發來的消息
Socket TCP 協議實現服務端和客戶端的簡單通訊-結合線程池的使用
文章目錄 前言 當前模式的弊端 服務端程式碼 客戶端程式碼 執行結果 客戶端 服務端
從零開始學Socket:(二)連線服務端和客戶端
先了解一下執行緒問題,在Main函式裡就是主執行緒他能處理程式碼,而new Thread就是新開一個執行緒,他和主執行緒互不干預,但是主執行緒完了,他也完了。他完了,主執行緒沒事。 在上篇部落格裡,我們已經建立好了伺服器端和客戶端,但是他們倆還沒有聯絡,要把他們聯絡起來,就
從零開始學Socket:(一)服務端和客戶端建立
上篇我提到Socket是TCP/IP的抽象介面。所以我們直接使用就好,沒必要知其甚解。 1.開啟VS 新建專案 名稱,位置隨意 這裡名稱是Server 框架選.NET 4.5(在這篇部落格裡也無所謂) 注意引用 using System.Net; using
Linux下網路socket程式設計——實現伺服器(select)與多個客戶端通訊
Linux下網路socket程式設計——實現伺服器(select)與多個客戶端通訊 置頂 2017年06月23日 14:44:37 閱讀數:3225 標籤: socket程式設計伺服器與多個客戶端通epoll多路複用C語言網路程式設計 更多
C++中Socket程式設計入門
C++中Socket程式設計入門 轉載 :http://www.cnblogs.com/L-hq815/archive/2012/07/09/2583043.html 該作者也是轉載,為國外網站翻譯之作 本人在學習Socket程式設計時,在其他地方看到了不錯Socket入門文件,通俗