Я уже задавал вопрос об этой проблеме, но не нашел ответа, а также сообщение закрыто, и я не знаю, почему?? Тем не менее, я повторяю вопрос.
Я хочу соединить два TCP-сокета в простой архитектуре клиент-сервер и настраиваю две виртуальные машины для имитации двух машин, которые хотят взаимодействовать.
Вот клиентский код:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <errno.h>
int main(int argc, char ** argv) {
//controllo che la porta venga indicata in riga di comando
if (argc != 2) {
printf("Usage: %s <port>", argv[0]);
exit(0);
}
//variabili di controllo, socket e indirizzo
int port = atoi(argv[1]);
int sock;
struct sockaddr_in addr;
socklen_t addr_size;
char buffer[1024];
int n;
//chiamata a socket e subito dopo controllo
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("[-] Error while creating socket.\n");
exit(1);
}
printf("[+] TCP socket created. \n");
memset(&addr, '\0', sizeof(addr));//setto i byte a 0
//imposto gli attributi dell'indirizzo
addr.sin_family = PF_INET;
addr.sin_port = port;
addr.sin_addr.s_addr = INADDR_ANY;
//connetto la socket
n = connect(sock, (struct sockaddr*)&addr, sizeof(addr));
if (n < 0) {
printf("Error while connecting the socket...: %s\n", strerror(errno));
printf("Errno value = %d", errno);
exit(1);
}
printf("[+] Client connected.\n");
bzero(buffer, 1024);// azzero i byte del buffer
strcpy(buffer, "Hello World");
printf("Client: %s\n", buffer);
send(sock, buffer, strlen(buffer), 0); // mando il messaggio contenuto nel buffer
bzero(buffer, 1024);
recv(sock, buffer, sizeof(buffer), 0); //ricevo la risposta del server
printf("Server: %s\n", buffer);
close(sock); // chiudo la connessione lato client
printf("[+] Disconnected from the server");
return 0;
}
А вот код сервера:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main(int argc, char** argv) {
//controllo che da riga di comando venga inserita la porta a cui collegare la socket
if (argc != 2) {
printf("Usage: %s <port>", argv[0]);
exit(0);
}
//creo tutte le variabili che mi serviranno
int port = atoi(argv[1]); //porta presa da riga di comando
int server_sock, client_sock; //socket per server e client
struct sockaddr_in server_addr, client_addr; //struct per gestire gli indirizzi di server e client(IPv4, IPv6)
socklen_t addr_size; //lunghezza degli indirizzi
char buffer[1024]; //buffer per il trasferimento dei messaggi
int n; //variabile di controllo
//chiamata alla funzione socket che restituisce un valore int a server_sock
server_sock = socket(AF_INET, SOCK_STREAM, 0);
//controllo che la chiamata socket() abbia restituito un valore > 0, quindi esito della chiamata positivo
if (server_sock < 0) {
perror("[-] Error while creating socket.\n");
exit(1);
}
printf("[+] TCP socket created. \n");
//setto i byte della memoria a 0
memset(&server_addr, '\0', sizeof(server_addr));
//assegno i vari attributi dell'indirizzo
server_addr.sin_family = AF_INET;
server_addr.sin_port = port;
server_addr.sin_addr.s_addr = INADDR_ANY;
//chiamata alla funzione bind che associa la socket con la porta e ne metto il valore di ritorno in n
n = bind(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
//controllo che la chiamata precedente sia andata bene quindi n > 0
if (n < 0) {
perror("[-] Error while binding the socket.\n");
exit(1);
}
printf("[+] Socket binded to the port %d\n", port);
//metto in ascolto il server
int listenVar = 0;
listenVar = listen(server_sock, 5);
if (listenVar < 0) {
perror("[-] Error while setup listening phase...\n");
exit(1);
}
printf("[+] Listening...\n");
//ciclo su i client che si collegano al server
while(1) {
addr_size = sizeof(client_addr); // size dell'indirizzo del client
//chiamata alla funzione accept, che restituisce un valore int
client_sock = accept(server_sock, (struct sockaddr*)&client_addr, &addr_size);
if (client_sock < 0) {
perror("[-]Error while accepting the connection");
exit(1);
}
char ipString[40]; // stringa per salvare l'ip del client che si è collegato al server
inet_ntop(AF_INET, &client_addr, ipString, sizeof(client_addr)); //converto l'ip in un formato di testo
printf("[+] Client connected.\n Client IP:%s\n", ipString); //stampo l'indirizzo che si è collegato al server
bzero(buffer, 1024); //azzero i byte del buffer
recv(client_sock, buffer, sizeof(buffer), 0); //ricevo il messaggio dal client
printf("Client: %s\n", buffer); // stampo il messaggio salvato in buffer
bzero(buffer,1024); //riazzero il buffer
strcpy(buffer, "Hi from the server"); // passo una stringa nel buffer
printf("Server: %s\n", buffer);
send(client_sock, buffer, strlen(buffer), 0); // mando il messaggio del buffer al client
close(client_sock); //chiudo la connessione
printf("[+] Client disconnected.\n");
}
return 0;
}
У меня проблема с управлением функцией и возвращаемое значение errno
111, или соединение отказано, но я не понимаю почему. Я думаю, что проблем с настройкой соединения нет, потому что если я выполню команду nc
на машинах, они оба без проблем будут общаться.
Второй printf()
может не отображать правильное значение errno
, поскольку его может изменить первый printf()
. Вам нужно сохранить его в другой переменной или сделать одну printf()
.
Помимо отмеченного выше htons(port), в клиентской части этого кода нет адреса для подключения (и из-за этого возникает сообщение «отказано в соединении», если только это не локальное соединение). Тогда есть неправильная структура для получения адреса клиента перед печатью (должно быть .sin_addr) с помощью inet_ntop(). Может быть, еще какие-то такие маленькие ошибки. (В целом этот код выглядит как смесь стилей BSD и Linux, судя по используемым функциям/констам)
@NinoQuindici_Git «Я уже задавал вопрос об этой проблеме, но не нашел ответа, а также сообщение закрыто, и я не знаю почему?? Однако я повторно публикую вопрос». - Я не вижу более раннего сообщения от вас. Но если бы он был и его закрыли, правильным действием было бы исправить любую проблему, из-за которой он закрылся, чтобы его можно было снова открыть. Просто сделайте репост того же вопроса еще раз.
На стороне клиента INADDR_ANY
(0.0.0.0) не является действительным IP-адресом для connect()
. На стороне сервера вы можете bind()
использовать серверный сокет, чтобы INADDR_ANY
прослушивать все локальные сетевые интерфейсы.
При звонке connect()
вам необходимо указать реальный IP-адрес сервера. Поскольку ваш клиент и сервер работают на разных виртуальных машинах, серверной виртуальной машине должен быть присвоен общедоступный IP-адрес, доступный с клиентской виртуальной машины.
Кроме того, вам необходимо использовать htons()
при присвоении значения полю sinaddr_in::sin_port
.
Привет, спасибо всем. Я изменил INADDR_ANY
в привязке на стороне клиента, затем изменил addr.sin_port = port
на htons(port)
(я не заметил этой ошибки до вашего комментария, поэтому не смог найти эту ошибку сам), и теперь все работает правильно! Большое спасибо!
addr.sin_port = port;
должно бытьaddr.sin_port = htons(port);