gpt4 book ai didi

c - Winsock 回显服务器端口

转载 作者:行者123 更新时间:2023-11-30 18:53:58 25 4
gpt4 key购买 nike

我正在尝试在 Windows 下移植这个简单的 TCP echo 程序 ( https://github.com/mafintosh/echo-servers.c/blob/master/tcp-echo-server.c ) 以用于教学目的。我的改编可以编译并运行,但不起作用:

**** 编辑:监听调用不知何故被切断。感谢雷米****

客户端连接,但没有收到任何回显。

移植的代码如下(错误消息是意大利语,但它们应该很清楚):

#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>

#define BUFFER_SIZE 1024
void on_error(char *s) { fprintf(stderr,"%s\n",s); fflush(stderr); exit(1); }

int main(int argc, char *argv[]) {
WSADATA wsadata;
int server_fd, client_fd, err;
struct sockaddr_in server, client;
char buf[BUFFER_SIZE];

int port = 6666;
int risultato = WSAStartup(MAKEWORD(2,2),&wsadata);
if (risultato != NO_ERROR)
{fprintf(stderr,"Errore in WSAStartup");fflush(stderr); exit(1);}

server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0) on_error("Non ho potuto creare il socket\n");
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = htonl(INADDR_ANY);

const char opt_val = 1;
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof opt_val);
/** bind & listen **/
err = bind(server_fd, (struct sockaddr *) &server, sizeof(server));
if (err < 0) on_error("Non ho potuto fare il bind del socket\n");
err = listen(server_fd, 128);
if (err < 0) on_error("Non ho potuto mettermi in ascolto sul socket\n");
printf("SERVER LISTENING ON PORT %d\n", port);

while (1) {
int client_len = sizeof(client);
do {
client_fd = accept(server_fd, (struct sockaddr *) &client, &client_len);
} while ( client_fd = SOCKET_ERROR);

if (client_fd < 0) on_error("Non riesco a stabilire una nuova connessione\n");

while (1) {
int read = recv(client_fd, buf, BUFFER_SIZE, 0);

if (!read) break;
if (read < 0) on_error("Errore nella lettura dal client\n");

err = send(client_fd, buf, read, 0);
if (err < 0) on_error("Errore nella scrittura verso il client\n");
}
}

WSACleanup();
return 0;
}

最佳答案

您正在调用bind()设置监听端口,但您没有调用 listen()在输入 accept() 之前实际开始监听端口循环。

一旦你修正了这个错误,你的 accept()无论如何,循环都会被破坏,因为它强制 client_fdSOCKET_ERROR即使accept()是成功的。您的while()条件是使用=当需要使用==时赋值运算符而是比较运算符。你应该检查 INVALID_SOCKET而不是SOCKET_ERROR .

话虽如此,还有一些其他事情需要考虑:

  • WinSock 不使用int为了表示套接字,它使用 SOCKET相反,这是 UINT_PTR 。检查无效套接字句柄时,请勿使用 < 0 ,使用== INVALID_SOCKET反而。

  • 大多数套接字函数通过 WSAGetLastError() 返回错误代码(WSAStartup() 是一个异常(exception))。养成使用它的习惯,并在输出消息中报告错误代码,这样您就知道为什么会失败。

  • SO_REUSEADDR预计 BOOL值,而不是 char值(value)。一个BOOLint 的 typedef因此是 4 个字节。

  • 并非所有套接字错误都是致命的,因此如果出现recv(),则不应终止整个服务器。/send()操作因非 fatal error 而失败。

  • send()不保证发送您要求发送的所有内容,因此您应该考虑到这一点。

  • 使用完接受的客户端套接字后,不要忘记关闭它。

试试这个:

#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>

#define BUFFER_SIZE 1024

void on_error(char *s, int *errCode = NULL)
{
int err = (errCode) ? *errCode : WSAGetLastError();
fprintf(stderr, "%s: %d\n", s, err);
fflush(stderr);
exit(1);
}

int main(int argc, char *argv[])
{
WSADATA wsadata;
SOCKET server_fd, client_fd;
struct sockaddr_in server, client;
int port = 6666, err;
char buf[BUFFER_SIZE];

err = WSAStartup(MAKEWORD(2,2), &wsadata);
if (err != 0)
on_error("Errore in WSAStartup", &err);

server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == INVALID_SOCKET)
on_error("Non ho potuto creare il socket");

memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;

/** bind & listen **/
const BOOL opt_val = TRUE;
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, (char*)&opt_val, sizeof(opt_val));
err = bind(server_fd, (struct sockaddr *) &server, sizeof(server));
if (err == SOCKET_ERROR)
on_error("Non ho potuto fare il bind del socket");
err = listen(server_fd, 1);
if (err == SOCKET_ERROR)
on_error("Non ho potuto mettermi in ascolto sul socket");

printf("SERVER LISTENING ON PORT %d\n", port);

while (1)
{
int client_len = sizeof(client);
client_fd = accept(server_fd, (struct sockaddr *) &client, &client_len);

if (client_fd == INVALID_SOCKET)
on_error("Non riesco a stabilire una nuova connessione");

bool keepLooping = true;
do
{
int read = recv(client_fd, buf, BUFFER_SIZE, 0);

if (read == 0)
break;

if (read == SOCKET_ERROR)
{
err = WSAGetLastError();
if ((err != WSAENOTCONN) && (err != WSAECONNABORTED) && (err == WSAECONNRESET))
on_error("Errore nella lettura dal client", &err);
break;
}

char *pbuf = buf;
do
{
int sent = send(client_fd, pbuf, read, 0);
if (sent == SOCKET_ERROR)
{
err = WSAGetLastError();
if ((err != WSAENOTCONN) && (err != WSAECONNABORTED) && (err == WSAECONNRESET))
on_error("Errore nella scrittura verso il client", &err);

keepLooping = false;
break;
}

pbuf += sent;
read -= sent;
}
while (read > 0);
}
while (keepLooping);

closesocket(client_fd);
}

WSACleanup();
return 0;
}

关于c - Winsock 回显服务器端口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31461531/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com