Sieťové prepojenie - program v C
http://shoe.bocks.com/net/
http://www.linuxjournal.com/article/2333
Keďže sú to už staršie články, chcel som sa opýtať na ich aktuálnosť, prípadne na doporučenia na iné články/návody.
Pre pridávanie komentárov sa musíte prihlásiť.
getaddrinfo()
apod.). Odporucal by som este manualove stranky. Tie su o socketoch a programovanim v nich pomerne dopre spracovane.Ale ak by si chcel písať programy, ktoré už budú kompatibilné aj s IPv6 a nie len IPv4 tak to ti potom odporúčam prečítať neskôr aj niečo novšie.
Ospravedlňujem sa za nechtiac zle zvolenú sekciu na fóre.
Kompilujem v konzole, takže je to operatívnejšie.
serverová aplikácia
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define MAXRCVLEN 500
int main(int argc, char *argv[])
{
struct sockaddr_in dest; /* socket info about the machine connecting to us */
struct sockaddr_in serv; /* socket info about our server */
int mast_socket; /* socket used to listen for incoming connection */
int con_socket; /* socket used for accepted connection */
char buffer[MAXRCVLEN + 1]; /* +1 so we can add null terminator */
int len; /* amount of sent or received data */
int port; /* port number */
socklen_t socksize = sizeof(struct sockaddr_in);
/* start program with port number */
if (argc != 2) {
fprintf(stderr, "Usage %s <port>\n", argv[0]);
return 1;
}
port = atoi(argv[1]);
/* create the master socket and check it worked */
if ((mast_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Creating master socket");
exit(EXIT_FAILURE);
}
/* zero the struct before filling the fields */
memset(&serv, 0, sizeof(serv));
serv.sin_family = AF_INET; /* set the type of connection to TCP/IP */
serv.sin_addr.s_addr = INADDR_ANY; /* set our address to any interface */
serv.sin_port = htons(port); /* set the server port number */
/* bind serv information to master socket */
if (bind(mast_socket, (struct sockaddr *)&serv, socksize) == -1) {
perror("bind()");
return 1;
}
/* start listening, allowing a queue of up to 1 pending connection */
if (listen(mast_socket, 1) == -1) {
perror("listen()");
return 1;
}
/* accept one connection */
if ((con_socket = accept(mast_socket, (struct sockaddr *)&dest,
&socksize)) == -1) {
perror("accept()");
return 1;
}
/* address of incomming connection */
printf("Incoming connection from %s\n", inet_ntoa(dest.sin_addr));
/* message "quit" ends receiving/sending data */
while (strcmp(buffer, "quit\n") != 0) { /* received end */
/* inserting data for sending */
printf("Enter data for client: ");
if (fgets(buffer, MAXRCVLEN, stdin) == NULL) {
fprintf(stderr, "fgets()\n");
return 1;
}
/* sending data */
if ((len = send(con_socket, buffer, strlen(buffer), 0)) == -1) {
perror("send()");
return 1;
}
printf("Sent: %d bytes\n", len);
/* it was sent message about end of connection */
if (strcmp(buffer, "quit\n") == 0)
break; /* finish at once */
/* receiving data */
if ((len = recv(con_socket, buffer, MAXRCVLEN, 0)) == -1) {
perror("recv()");
return 1;
}
/* have to null terminate the received data ourselves */
buffer[len] = '\0';
printf("From client: %s", buffer);
printf("Received: %d bytes\n", len);
}
/* shutdown sockets properly */
close(con_socket);
close(mast_socket);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define MAXRCVLEN 500
int main(int argc, char *argv[])
{
char buffer[MAXRCVLEN + 1]; /* +1 so we can add null terminator */
char *remote_host; /* server name or IP */
int my_socket; /* socket used for connection */
int len; /* amount of sent or received data */
int remote_port; /* server port number */
struct hostent *host_ptr; /* remote host */
struct sockaddr_in dest; /* socket info about server to connect */
socklen_t socksize = sizeof(struct sockaddr_in);
/* start program with sever name/IP and port number */
if (argc != 3) {
fprintf(stderr, "Usage %s <server_host> <server_port>\n", argv[0]);
return 1;
}
remote_host = argv[1];
remote_port = atoi(argv[2]);
/* resolve information about remote server */
if ((host_ptr = gethostbyname(remote_host)) == NULL) { /* from name */
if ((host_ptr = gethostbyaddr(remote_host, strlen(remote_host),
AF_INET)) == NULL) { /* or from IP number */
perror("Error resolving server address");
return 1;
}
}
/* create socket and check it worked */
if ((my_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Creating socket");
return 1;
}
/* zero the struct before filling the fields */
memset(&dest, 0, sizeof(dest));
dest.sin_family = AF_INET; /* set the type of connection to TCP/IP */
dest.sin_port = htons(remote_port); /* set destination port number */
/* set destination IP address */
memcpy(&(dest.sin_addr.s_addr), host_ptr->h_addr, host_ptr->h_length);
/* connect socket */
if (connect(my_socket, (struct sockaddr *)&dest, socksize) == -1) {
perror("connect()");
return 1;
}
/* message "quit" ends receiving/sending data */
while (strcmp(buffer, "quit\n") != 0) { /* sent end */
/* receiving data */
if ((len = recv(my_socket, buffer, MAXRCVLEN, 0)) == -1) {
perror("recv()");
return 1;
}
/* have to null terminate the received data ourselves */
buffer[len] = '\0';
printf("From server: %s", buffer);
printf("Received: %d bytes\n", len);
/* it was received message about end of connection */
if (strcmp(buffer, "quit\n") == 0)
break; /* finish at once */
/* inserting data for sending */
printf("Enter data for server: ");
if (fgets(buffer, MAXRCVLEN, stdin) == NULL) {
fprintf(stderr, "fgets()\n");
return 1;
}
/* sending data */
if ((len = send(my_socket, buffer, strlen(buffer), 0)) == -1) {
perror("send()");
return 1;
}
printf("Sent: %d bytes\n", len);
}
/* shutdown socket properly */
close(my_socket);
return 0;
}
Na Fedora 17 nastavujem sieťovú kartu cez
ifconfig eth0 192.168.1.1 netmask 255.255.255.0 up
Na Kubuntu
ifconfig eth0 192.168.1.2 netmask 255.255.255.0 up
Paradox je, že spojenie funguje iba v prípade, že na Kubuntu spustím serverovú aplikáciu a na Fedore spustím klientovu aplikáciu. Opačne to nefunguje.
Skúsil som aj navzájom vymeniť IP adresy, ale nepomohlo. Stále musím na Kubuntu spustiť serverový program a na Fedore klientov program.
Vedel by mi niekto poradiť, prečo to tak je?
Je dosť možné, že sa triafaš na už obsadené porty, alebo nemáš právo na vytvorenie konekcie na porte pod 1024.
Podotýkam, že programy fungujú správne, ako som vyššie uviedol.
Lenže len pri kombinácií server - live cd, klient - installed system.
Kombinácia klient - live cd, server - installed system vypíše cez perror hlášku
Connection refused
.Pokiaľ testujem server/klient na localhost-e fungujú v jednom aj druhom poradí bez problémov.
Nanešťastie nemám k dispozícií dva plnohodnotné systémy s plnou inštaláciou, takže neviem identifikovať, či správanie sa programov je dané druhým live systémom alebo nie.
Bez toho že si pozrieš kód chyby, a preložíš si to do textu, tak nebudeš vedieť v čom je chyba. A reagovanie na základe odhadu z čítania kryštáľovej gule má posledný príslevok. Skontroluj si firewall či neblokuješ pripojenie. Chyba connection refused má množstvo dôvodov.
Napr. výstup z tohto programu bude
perror: No such file or directory
strerror No such file or directory
Funkcia perror() umožňuje obohatiť výpis podľa errno o vlastný komentár.
Ale, to nič nemení na tom, že si tie ostatné veci neskontroloval. Takže, s radosťou do toho.
Nahodil som na oba počítače Kubuntu 9.10 live, prepojil káblom, nastavil IPčky, nahral cez USB skomplivané programy server_tcp a client_tcp. Spustil som tak aj naopak a fungovalo bez problémov.
Takže problém bol v zabezpečení Fedora 17.
Programy sú v poriadku.