我摆脱了错误,现在我似乎还停留在其他东西上。
我在Code :: Blocks上有单独的Winsock客户端和服务器程序。我正在尝试从客户端向服务器发送消息,但是服务器程序似乎在accept()函数之前冻结了,除了“侦听传入的连接”之外什么也没做。输出。客户端缓冲区中的消息永远不会显示在服务器控制台中。
服务器程序中的accept函数肯定看起来有问题。这似乎是服务器程序冻结的地方。我尝试在那之后键入随机的提示行,但没有输出。
在“消息已发送”之后,客户端似乎也冻结了。但是几分钟后,我收到“ recv failed”,然后收到“ Reply Received”,然后出现一系列表情符号。我想我下面有链接的图片。
这是我的客户代码:
#include <iostream>
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main()
{
WSADATA wsaData;
SOCKET sock;
sockaddr_in server;
char *buffer, server_reply[2000];
int recv_size;
int iResult;
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
} else {
printf("WSAStartup successful!: %d\n", iResult);
}
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET){
printf("Socket not created.\n");
} else {
printf("Socket created.\n");
}
server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(80);
if(connect(sock, (SOCKADDR *)&server, sizeof(server)) != 0){
printf("Connect Error : %d" , WSAGetLastError());
} else {
printf("Connected\n");
};
buffer = "Hello there!";
send(sock, buffer, sizeof(buffer), 0);
printf("Message Sent.\n");
if((recv_size = recv(sock , server_reply , 2000 , 0)) == SOCKET_ERROR)
{
puts("recv failed");
}
puts("Reply received\n");
//Add a NULL terminating character to make it a proper string before printing
server_reply[recv_size] = '\0';
puts(server_reply);
closesocket(sock);
WSACleanup();
return 0;
}
这是我的服务器代码:
#include <iostream>
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main()
{
WSADATA wsaData;
SOCKET server1, client;
sockaddr_in serverAddr, clientAddr;
int iResult;
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
} else {
printf("WSAStartup successful!: %d\n", iResult);
}
server1 = socket(AF_INET, SOCK_STREAM, 0);
if (server1 == INVALID_SOCKET){
printf("Socket not created.\n");
} else {
printf("Socket created.\n");
}
serverAddr.sin_addr.S_un.S_addr = INADDR_ANY;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(8888);
if(bind(server1, (SOCKADDR *)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR){
printf("Bind failed. : %d" , WSAGetLastError());
} else {
printf("Bind successful.\n");
}
if(listen(server1, SOMAXCONN) != 0){
printf("Server not listening. : %d" , WSAGetLastError());
} else {
cout << "Listening for incoming connections..." << endl;
}
char buffer[1024];
int clientAddrSize = sizeof(clientAddr);
if((client = accept(server1, (SOCKADDR *)&clientAddr, &clientAddrSize)) == INVALID_SOCKET)
{
printf("Connect Error : %d" , WSAGetLastError());
} else {
cout << "Client connected!" << endl;
recv(client, buffer, sizeof(buffer), 0);
cout << "Client says: " << buffer << endl;
memset(buffer, 0, sizeof(buffer));
closesocket(client);
closesocket(server1);
cout << "Client disconnected." << endl;
}
WSACleanup();
return 0;
}
我正在尝试使用CodeBlocks中的C ++构建与我的客户端程序一起使用的Winsock服务器程序。但是,accept函数返回错误代码10022,根据我的理解,该错误代码表示参数无效。我看不到accept函数中的任何参数都无效。感谢您的帮助!
int main()
{
WSADATA wsaData;
SOCKET server1, client;
sockaddr_in serverAddr, clientAddr;
int iResult;
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
} else {
printf("WSAStartup successful!: %d\n", iResult);
}
server1 = socket(AF_INET, SOCK_STREAM, 0);
if (server1 == INVALID_SOCKET){
printf("Socket not created.\n");
} else {
printf("Socket created.\n");
}
serverAddr.sin_addr.S_un.S_addr = inet_addr(INADDR_ANY);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(8888);
bind(server1, (SOCKADDR *)&serverAddr, sizeof(serverAddr));
listen(server1, SOMAXCONN);
cout << "Listening for incoming connections..." << endl;
char *buffer;
int clientAddrSize = sizeof(clientAddr);
if((client = accept(server1, (SOCKADDR *)&clientAddr, &clientAddrSize)) == INVALID_SOCKET)
{
printf("Connect Error : %d" , WSAGetLastError());
} else {
cout << "Client connected!" << endl;
recv(client, buffer, sizeof(buffer), 0);
cout << "Client says: " << buffer << endl;
memset(buffer, 0, sizeof(buffer));
closesocket(client);
closesocket(server1);
cout << "Client disconnected." << endl;
}
WSACleanup();
return 0;
}
答案 0 :(得分:2)
10022为WSAEINVAL
。根据{{3}}文档:
WSAEINVAL
listen
函数未在accept
之前调用。
accept()
文档还说:
WSAEINVAL
10022无效的参数。
提供了一些无效的参数(例如,为
setsockopt
函数指定了无效的级别)。在某些情况下,它还引用套接字的当前状态,例如在未监听的套接字上调用accept
。
好的,让我们来看一下您的listen()
通话:
listen(server1, SOMAXCONN);
假设server1
是一个有效的套接字(您可以检查一下,但是如果socket()
失败则不停止程序),这没什么异常。
您没有检查任何listen()
错误。根据{{3}}文档,可能的错误之一是:
WSAEINVAL
套接字尚未与bind
绑定。
好的,接下来让我们看看您的bind()
通话:
bind(server1, (SOCKADDR *)&serverAddr, sizeof(serverAddr));
同样,您没有检查任何bind()
错误。根据{{3}}文档,可能的错误之一是:
WSAEADDRNOTAVAIL
请求的地址在其上下文中无效。如果name参数所指向的指定地址不是此计算机上的有效本地IP地址,则会返回此错误。
您可能会得到,因为您没有正确地填充serverAddr
,特别是在此行上
serverAddr.sin_addr.S_un.S_addr = inet_addr(INADDR_ANY);
INADDR_ANY
被定义为0
,因此您将S_addr
字段设置为inet_addr(0)
的结果,该结果无效,因此INADDR_NONE
(0xFFFFFFFF )返回,这也是您无需检查的内容。正确的分配方法是按原样使用INADDR_ANY
:
serverAddr.sin_addr.S_un.S_addr = INADDR_ANY;
因此,总结起来,您的错误处理是不充分的,允许错误累积,直到您最终决定完全对accept()
进行错误处理为止,为时已晚。您需要一路检查每个函数的结果是否失败,遇到错误时请停止。
答案 1 :(得分:1)
glimpse()
采用inet_addr
,它以数字和点表示法表示IPv4地址。您正在将const char*
传递给此函数,它可以编译但无法正常工作,因为INADDR_ANY
等于0,因此使用空指针调用INADDR_ANY
。您应该检查该函数的返回码,-1表示错误。我想你明白了。
如果您想绑定任何本地地址,则应将inet_addr
与INADDR_ANY
结合使用:
htonl
此
serverAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
导致不确定的行为。缓冲区未初始化。对此char *buffer;
recv(client, buffer, sizeof(buffer), 0);
的调用要读取4/8字节-recv
,并写入未初始化的 buffer 指针。您需要创建一些初始大小的缓冲区,例如通过调用malloc / calloc:
sizeof(buffer)