[英]Problem in accepting connection from client (socket programming) in Visual C++
我已經用Visual C ++編寫了一個簡單的單線程客戶端服務器應用程序。 當我運行我的服務器時,我等待一段時間它接受來自客戶端的一些請求。
當我將客戶端連接到服務器時。 客戶端上的日志消息報告發送14個字節,服務器上沒有消息。 我已經編寫了一個print語句來打印控制台上服務器接受的內容,但服務器不打印任何內容。
在我看來,客戶端已連接到其他服務器。
客戶端和服務器代碼如下。
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <conio.h>
#define DEFAULT_PORT "27015"
#define DEFAULT_BUFLEN 512
#pragma comment(lib, "Ws2_32.lib")
int main() {
WSADATA wsdata;
int result = WSAStartup(MAKEWORD(2,2),&wsdata);
if (result != 0){
printf("%s","Unable to initilize windows socket\n");
getch();
return 1;
}
struct addrinfo *addrResult = NULL,hints;
ZeroMemory(&hints, sizeof (hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
result = getaddrinfo(NULL,DEFAULT_PORT,&hints,&addrResult);
if (result != 0){
printf("%s","Error in getaddrInfo");
getch();
return 1;
}
SOCKET listenSocket = INVALID_SOCKET;
listenSocket = socket(addrResult->ai_family,addrResult->ai_socktype,addrResult->ai_protocol);
if (listenSocket == INVALID_SOCKET){
printf("%s","Error in creating socket object\n");
getch();
closesocket(listenSocket);
WSACleanup();
return 1;
}
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("127.0.0.1");
service.sin_port = htons(27015);
if (bind(listenSocket,addrResult->ai_addr,
(int)addrResult->ai_addrlen) == SOCKET_ERROR){
//if(bind(listenSocket,(SOCKADDR*) &service,
// sizeof(service)) == SOCKET_ERROR){
printf("bind failed: %d\n", WSAGetLastError());
freeaddrinfo(addrResult);
closesocket(listenSocket);
WSACleanup();
getch();
return 1;
}
freeaddrinfo(addrResult);
if (listen(listenSocket,SOMAXCONN) == SOCKET_ERROR){
printf("%s","Error in listening socket");
getch();
closesocket(listenSocket);
WSACleanup();
}
SOCKET clientSocket = INVALID_SOCKET;
clientSocket = accept((listenSocket,NULL,NULL);
if (clientSocket == INVALID_SOCKET){
closesocket(listenSocket);
WSACleanup();
}
char recvbuf[DEFAULT_BUFLEN];
int iRecvResult, iSendResult;
int recvbuflen = DEFAULT_BUFLEN;
do{
iRecvResult = 0;
iSendResult = 0;
iRecvResult = recv(clientSocket,recvbuf,recvbuflen,0);
if (iRecvResult > 0){
printf("Bytes received: %d\n", iRecvResult);
getch();
// Echo the buffer back to the sender
iSendResult = send(clientSocket, recvbuf, iRecvResult, 0);
if (iSendResult == SOCKET_ERROR) {
printf("send failed: %d\n", WSAGetLastError());
closesocket(clientSocket);
WSACleanup();
return 1;
}
printf("Bytes sent: %d\n", iSendResult);
}
else if (iRecvResult == 0){
printf("Connection closing...\n");
}
else{
printf("recv failed: %d\n", WSAGetLastError());
closesocket(clientSocket);
WSACleanup();
return 1;
}
}while(iRecvResult > 0);
getch();
return 0;
}
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <conio.h>
#define DEFAULT_PORT "27015"
#define DEFAULT_BUFLEN 512
#pragma comment(lib, "Ws2_32.lib")
int main(){
WSADATA wsdata;
WSAStartup(MAKEWORD(2,2),&wsdata);
struct addrinfo *addrResult = NULL,hints;
ZeroMemory(&hints, sizeof (hints));
hints.ai_protocol = IPPROTO_TCP;
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_UNSPEC;
int result = 0;
if (getaddrinfo("127.0.0.1",DEFAULT_PORT,
&hints,&addrResult)){
printf("%s","Error in getaddrInfo\n");
WSACleanup();
getch();
return 1;
}
SOCKET connectingSocket = INVALID_SOCKET;
connectingSocket = socket(addrResult->ai_family,addrResult->ai_socktype,
addrResult->ai_protocol);
if (connectingSocket == INVALID_SOCKET){
printf("%s","Error in creating socket\n");
freeaddrinfo(addrResult);
WSACleanup();
getch();
return 1;
}
if (connect(connectingSocket,addrResult->ai_addr, (int)addrResult->ai_addrlen) != 0){
closesocket(connectingSocket);
connectingSocket = INVALID_SOCKET;
WSACleanup();
}
freeaddrinfo(addrResult);
int recvbuflen = DEFAULT_BUFLEN;
char *sendbuf = "this is a test";
char recvbuf[DEFAULT_BUFLEN];
int iResult;
// Send an initial buffer
iResult = send(connectingSocket, sendbuf, (int) strlen(sendbuf), 0);
if (iResult == SOCKET_ERROR) {
printf("send failed: %d\n", WSAGetLastError());
closesocket(connectingSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %ld\n", iResult);
// shutdown the connection for sending since no more data will be sent
// the client can still use the connectingSocket for receiving data
iResult = shutdown(connectingSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(connectingSocket);
WSACleanup();
return 1;
}
// Receive data until the server closes the connection
do {
iResult = recv(connectingSocket, recvbuf, recvbuflen, 0);
if (iResult > 0)
printf("Bytes received: %d\n", iResult);
else if (iResult == 0)
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
} while (iResult > 0);
getch();
return 0;
}
當客戶端嘗試通過增強診斷來發送時,您可以確認服務器代碼中發生的情況。 在重要時間輸出更多(例如成功的connect()
, accept()
, close()
,所有套接字錯誤,可選的send/recv
流量日志文件)可能會很快指向解決方案。 確保檢查並輸出所有套接字API調用上的任何錯誤。
您可以使用netstat
檢查偵聽目標端口/地址的其他系統。
我看不出任何明顯的錯誤。
嗯...在修復了明顯的語法錯誤( clientSocket = accept((listenSocket,NULL,NULL);
的不匹配的開括號clientSocket = accept((listenSocket,NULL,NULL);
)后,它對我來說似乎運行得相當好。在服務器上我得到:
收到的字節數:14
發送的字節數:14
連接正在關閉...
在客戶端:
發送的字節數:14
收到的字節數:14
recv失敗:10054
因此,客戶端將14個字節發送到服務器(按Enter鍵),服務器將這14個字節回顯到客戶端(再次按Enter鍵),然后服務器關閉連接。 客戶端讀取14個字節,然后在連接關閉時進一步讀取失敗。
編輯:我通過打開兩個Windows SDK命令提示符窗口來運行代碼,其中一個運行server
,另一個運行client
,這兩個都沒有特別令人興奮或不同尋常的地方。
我建議你做以下事情:
netstat -a -b | grep -e“ 27015” --after = 1
如果此命令的輸出不為空 - 您將看到作為問題根源的應用程序的名稱。 否則,嘗試通過運行服務器然后 - 客戶端來重現您的問題。 如上所述(或通過tcpview
程序)通過netstat命令監視服務器的狀態。 有趣的結果是什么。
Offtopic note:您的斷開序列不完整。 谷歌graceful disconnect
。 通常它看起來像這樣:
[ client ]發出shutdown (sd_send)並等待來自服務器的剩余數據
[ server ]如果recv ()== 0則{ send (剩余數據); 發出shutdown (sd_send); closesocket }
[ 客戶 ]收到剩余數據; 如果recv ()== 0則關閉
在客戶端中,您正在關閉發送連接:
// shutdown the connection for sending since no more data will be sent
// the client can still use the connectingSocket for receiving data
iResult = shutdown(connectingSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(connectingSocket);
WSACleanup();
return 1;
}
服務器檢測到斷開連接(recv返回0)並在不關閉其側面連接的情況下完成,這就是您收到錯誤100054的原因。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.