我有一个简单的问题。
至少我认为这很简单!
我正在做一个大学项目,我构建了一个服务器客户端即时消息服务,其结构如下:
-服务器创建
套接字
侦听客户端请求
-除了其他功能外,每个客户端都可以向另一个客户端发送消息包(即使是脱机)
使用UDP
我为服务器使用了端口4242,然后尝试为两个示例客户端使用4243和4244。
我的问题是:这些端口是否不可用于UDP通信?
我这样问是因为当我尝试向这些端口发送消息时,接收客户端会获取并打印“奇怪”字符串。
准确地说
,因为它存储了先例消息,并首先打印新消息,然后打印一大块先例消息。
另一方面,如果我使用例如4303和4486,它将按预期工作。
我看到了那些数字
Wikipedia
,但由于我不确定如何解释该表(因此,如果我解释正确的话),而且我知道维基百科不太可靠,我想我可以在这里问一下。
另一方面,如果我提供的链接不可靠,是否有任何命令或资源来检查这些内容?
提前感谢!
编辑:
这是我的密码!我以前无法上传。。我也会试着给你一个简短的解释。
正如我在评论中提到的,我认为我已经收到了,但一个客户没有收到另一个客户的消息。所以,所有的工作,除了!发送功能,我想。。。
客户
客户端是使用“!register username”连接到服务器的用户;此命令:
-如果客户端是第一次连接到该服务,则将其注册到该服务,并将其设置为“联机”
-如果客户端已注册到服务,则重新连接客户端;在这种情况下,如果有一些脱机消息,服务器会将其传递给te客户端
连接后,客户端可以使用以下命令:
1) 哦!帮助:显示可用命令
2) 哦!谁:显示在线用户
3) 哦!注销:正如nam所建议的,从服务器注销客户端
4) 哦!发送用户名:如果目标客户端联机,服务器返回UDP目标地址和端口,客户端直接发送消息;如果目标客户端脱机,服务器将存储消息,以便在连接目标客户端后将其发送到目标客户端
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>
#define DIM 1024
#define ADDR_DIM 16
#define PORT_DIM 5
#define CMD_DIM 12
#define NAME_DIM 21
void cl_help(int sckt) {
int rv, length, l;
char* text = "!help";
char answer[DIM];
length = strlen(text);
l = htons(length);
//Sending command dimension
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) text, length, 0);
if(rv < 0) {};
//Sending the command itself
rv = recv(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
length = ntohs(l);
rv = recv(sckt, (void*) answer, length, 0);
if(rv < 0) {};
answer[length] = '\0';
puts(answer);
}
void cl_quit(int sckt) {
int rv, length, l;
char* text = "!quit";
char answer[DIM];
length = strlen(text);
l = htons(length);
//Sending command dimension
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) text, length, 0);
if(rv < 0) {};
//Sending the command itself
rv = recv(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
length = ntohs(l);
rv = recv(sckt, (void*) answer, length, 0);
if(rv < 0) {};
answer[length] = '\0';
puts(answer);
}
void cl_who(int sckt) {
int rv, length, l, n_net, n, i;
char* text = "!who";
char answer[DIM];
length = strlen(text);
l = htons(length);
//Sending the dimension of the command
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) text, length, 0);
if(rv < 0) {};
//Sending the command itself
rv = recv(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
length = ntohs(l);
rv = recv(sckt, (void*) answer, length, 0);
if(rv < 0) {};
answer[length] = '\0';
puts(answer);
if( (strcmp(answer, "Nessun utente in linea") != 0)\
&& (strcmp(answer, "Devi essere connesso per poter utilizzare questa funzione") != 0) ) { //No user online; Yuo have to be registered
//Receiving number of users online
rv = recv(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
length = ntohs(l);
rv = recv(sckt, (void*) &n_net, length, 0);
if(rv < 0) {};
n = ntohs(n_net);
//Getting every username
for(i=0; i<n; i++) {
rv = recv(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
length = ntohs(l);
rv = recv(sckt, (void*) answer, length, 0);
if(rv < 0) {};
answer[length] = '\0';
puts(answer);
};
};
}
void cl_deregister(int sckt) {
int rv, length, l;
char* text = "!deregister";
char answer[DIM];
//Sending command dimension
length = strlen(text);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) text, length, 0);
if(rv < 0) {};
//Receiving answer
rv = recv(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
length = ntohs(l);
rv = recv(sckt, (void*) answer, length, 0);
if(rv < 0) {};
answer[length] = '\0';
puts(answer);
}
void cl_register(int sckt, char* name, char* port) {
int rv, length, l, n, n_net, i;
char msg[DIM+NAME_DIM+4];
char answer[DIM];
sprintf(msg, "!register %s %s", name, port);
//Sending command
length = strlen(msg);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) msg, length, 0);
if(rv < 0) {};
//Receiving answer
rv = recv(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
length = ntohs(l);
rv = recv(sckt, (void*) answer, length, 0);
if(rv < 0) {};
answer[length] = '\0';
puts(answer);
if(strcmp(answer, "L'utente era gia' registrato al servizio: riconnessione completata.\n") == 0) { //Users already registered: reconnection
//Receiving info
rv = recv(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
length = ntohs(l);
rv = recv(sckt, (void*) answer, length, 0);
if(rv < 0) {};
answer[length] = '\0';
puts(answer);
if(strcmp(answer, "Messaggi offline presenti.") == 0) { //Offline messages found
//Receiving the number of messages
rv = recv(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
length = ntohs(l);
rv = recv(sckt, (void*) &n_net, length, 0);
if(rv < 0) {};
n = ntohs(n_net);
//Recevingi messages
for(i=0; i<n; i++) {
rv = recv(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
length = ntohs(l);
rv = recv(sckt, (void*) msg, length, 0);
if(rv < 0) {};
msg[length] = '\0';
puts(msg);
};
};
};
}
void cl_send(int sckt, int udp_sd, char* name, char* info, char* source) {
struct sockaddr_in dest;
int rv, length, l,p;
char msg[DIM+NAME_DIM+4];
char address[ADDR_DIM];
char port[PORT_DIM];
char answer[DIM];
char *pointer;
sprintf(msg, "!send %s", name);
//Sending command
length = strlen(msg);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) msg, length, 0);
if(rv < 0) {};
//Receiving answer
rv = recv(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
length = ntohs(l);
rv = recv(sckt, (void*) answer, length, 0);
if(rv < 0) {};
answer[length] = '\0';
puts(answer);
if(strcmp(answer, "Devi essere connesso per poter utilizzare questa funzione.\n") != 0) { //You have to be registered
if(strncmp(answer, "Client attualmente connesso", 27) == 0) { //User connected right now
pointer = answer+29; //to get only the address and the port number
sscanf(pointer, "%s %s", address, port);
address[ADDR_DIM] = '\0';
port[PORT_DIM] = '\0';
p = ntohs(atoi(port));
memset(&dest, 0, sizeof(dest));
memset(&msg, 0, sizeof(msg));f
//Destination UDP socket
dest.sin_family = AF_INET;
dest.sin_port = htons(p);
inet_pton(AF_INET, address, &dest.sin_addr);
//Sending direct message using UDP
sprintf(msg, "%s > ", source);
strcat(msg, info);
length = strlen(msg);
l = htons(length);
//Sending message
rv = sendto(udp_sd, (void*) &l, sizeof(l), 0, (struct sockaddr*) &dest, sizeof(dest));
if(rv < 0) {};
rv = sendto(udp_sd, (void*) msg, length, 0, (struct sockaddr*) &dest, sizeof(dest));
if(rv < 0) {};
} else { //Offline transmission: transmits message to server using TCP
length = strlen(info);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) info, length, 0);
if(rv < 0) {};
//Getting info from the server
rv = recv(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
length = ntohs(l);
rv = recv(sckt, (void*) answer, length, 0);
if(rv < 0) {};
answer[length] = '\0';
puts(answer);
};
};
}
int main(int argc, char* argv[]) {
struct sockaddr_in srv_addr;
struct sockaddr_in my_addr;
int sd, udp;
int err;
int pid;
int length, l;
char buffer[DIM];
char cmd[CMD_DIM];
char dest[NAME_DIM];
char my_name[NAME_DIM];
char in[DIM];
char to_send[DIM+NAME_DIM+4];
char part[DIM] = "";
if(argc != 5) {
//Check argument
exit(EXIT_FAILURE);
};
//TCP socket
sd = socket(AF_INET, SOCK_STREAM, 0);
//UDP socket
udp = socket(AF_INET, SOCK_DGRAM, 0);
//Pulizia
memset(&srv_addr, 0, sizeof(srv_addr));
memset(&my_addr, 0, sizeof(my_addr));
//TCP server parameters
srv_addr.sin_family = AF_INET;
srv_addr.sin_port = htons(atoi(argv[4]));
inet_pton(AF_INET, argv[3], &srv_addr.sin_addr);
//my UDP parameters
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(atoi(argv[2]));
inet_pton(AF_INET, argv[1], &my_addr.sin_addr);
//Bind for UDP socket
err = bind(udp, (struct sockaddr*) &my_addr, sizeof(my_addr));
if(err < 0) {};
//Connecting to the server
err = connect(sd, (struct sockaddr*) &srv_addr, sizeof(srv_addr));
if(err < 0) {};
//Auto-sending help command to display available operations
strcpy(cmd, "!help");
length = strlen(cmd);
l = htons(length);
err = send(sd, (void*) &l, sizeof(l), 0);
if(err < 0) {};
err = send(sd, (void*) cmd, length, 0);
if(err < 0) {};
//Receiving info from the server -> available operations
err = recv(sd, (void*) &l, sizeof(l), 0);
if(err < 0) {};
length = ntohs(l);
err = recv(sd, (void*) buffer, length, 0);
if(err < 0) {};
buffer[strlen(buffer)] = '\0';
puts(buffer);
pid = fork();
if(pid == 0) {
//Child
close(sd);
while(1) {
memset(to_send, 0, sizeof(to_send));
err = recvfrom(udp, (void*) &l, sizeof(l), 0, 0, 0);
if(err < 0) {
puts("error recvfrom");
exit(EXIT_FAILURE);
};
length = ntohs(l);
err = recvfrom(udp, (void*) to_send, length, MSG_WAITALL, 0, 0);
if(err < 0) {
puts("error recvfrom");
exit(EXIT_FAILURE);
};
to_send[length] = '\0';
puts(to_send);
};
} else {
//Parent
while(1) {
//Asking the user to prompt the command
memset(cmd, 0, sizeof(cmd));
memset(in, 0, sizeof(in));
memset(dest, 0, sizeof(dest));
puts("\nInserisci un comando: "); //Insert a command
fgets(in, DIM, stdin);
in[strlen(in)-1] = '\0';
sscanf(in, "%s", cmd);
cmd[CMD_DIM-1] = '\0';
if(strcmp(cmd, "!help") == 0) {
cl_help(sd);
continue;
};
if(strcmp(cmd, "!deregister") == 0) {
cl_deregister(sd);
};
if(strcmp(cmd, "!register") == 0) {
sscanf(in, "%s %s", cmd, dest);
cmd[CMD_DIM-1] = '\0';
dest[NAME_DIM-1] = '\0';
strcpy(my_name, dest);
if(strlen(dest) == 0) { //to avoid an empty username
puts("Errore: non hai inserito alcun username; riprova.\n"); //Please insert an username
} else {
cl_register(sd, dest, argv[2]);
};
continue;
};
if(strcmp(cmd, "!who") == 0) {
cl_who(sd);
continue;
};
if(strcmp(cmd, "!send") == 0) {
sscanf(in, "%s %s", cmd, dest);
cmd[CMD_DIM-1] = '\0';
dest[NAME_DIM-1] = '\0';
while(1) {
memset(part, 0, sizeof(part));
fgets(part, DIM-(strlen(to_send)-NAME_DIM-4), stdin);
l = strlen(part);
if((part[l-2] == '.') && (part[l-1] == '\n') && (strlen(part) == 2)) {
part[l-2] = '\0';
break;
} else {
strcat(to_send, part);
};
if(strlen(to_send) >= DIM+NAME_DIM+3) {
to_send[DIM+NAME_DIM+3] = '\0';
break;
};
};
strcat(to_send, "\0");
cl_send(sd, udp, dest, to_send, my_name);
memset(to_send, 0, sizeof(to_send)); //to empty the buffer used to store the message sent
continue;
};
if(strcmp(cmd, "!quit") == 0) {
cl_quit(sd);
close(sd);
break;
} else{
puts("Comando non valido.\n"); //Not a valid command
};
};
};
return 0;
}
服务器
服务器响应来自客户端的请求,并被构造为并发服务器。
#include <sys/mman.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#define MAX_CONN 100
#define DIM 1024
#define ADDR_DIM 16
#define CMD_DIM 12
#define NAME_DIM 20
#define MSG_DIM DIM+NAME_DIM+4
#define PORT_DIM 5
#define MAX_UTN 1024
struct users {
char username[NAME_DIM];
char status; //c = connected, o = offline
struct sockaddr_in address;
char pendent[DIM][DIM];
char sender[DIM][NAME_DIM];
int msg; //last message to be sent
};
void srv_help(int sckt) {
int rv, length, l;
char* text = "Sono disponibili i seguenti comandi: \n\
!help --> mostra l'elenco dei comandi disponibili \n\
!register username --> registra il client presso il server\n\
!deregister --> de-registra il client presso il server\n\
!who --> mostra l'elenco degli utenti disponibili\n\
!send username --> invia un messaggio ad un altro utente\n\
(messaggio subito dopo comando\n\
!quit --> disconnette il client dal server ed esce\n\
('username': max 20 caratteri)\n\
(per terminare messaggio inserisci un . da solo)\n";//info about the available commands
length = strlen(text);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) text, length, 0);
if(rv < 0) {};
};
void srv_who(int sckt, struct users* reg, int last) {
int i, rv, length, l;
char text[DIM];
strcpy(text, "Nessun utente in linea\n");//No user online
if(last == 0) { //if no user is online
length = strlen(text);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) text, length, 0);
if(rv < 0) {};
} else {
strcpy(text, "Utenti in linea:\n"); //Users online:
length = strlen(text);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) text, length, 0);
if(rv < 0) {};
//Here I send the number of users online, to synchronize server and client
length = sizeof(last);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
l = htons(last);
rv = send(sckt, (void*) &l, length, 0);
if(rv < 0) {};
//Transmitting users
for(i=0; i<last; i++) {
if(reg[i].status == 'c') {
length = strlen(reg[i].username);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) reg[i].username, length, 0);
if(rv < 0) {};
};
};
};
};
void srv_deregister(int sckt, struct users* reg, char* name, int* last) {
int i, rv, length, l;
char text[DIM];
strcpy(text, "Deregistrazione completata.\n"); //De-registration completed
for(i=0; i<*last; i++) {
if(strcmp(reg[i].username, name) == 0) { //user found
reg[i] = reg[*last];
(*last)--;
length = strlen(text);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) text, length, 0);
if(rv < 0) {};
return;
};
};
}
int srv_register(int sckt, struct users* reg, char* name, struct sockaddr_in client, int p, int* last) { //char*
int i, rv, length, l, j, pos;
//char pos[MSG_DIM]; // = "";
char text[DIM];
char buffer[MSG_DIM];
memset(text, 0, DIM);
strcpy(text, "Registrazione effettuata con successo.\n"); //Registration completed
for(i=0; i<*last; i++) {
if(strcmp(reg[i].username, name) == 0) { //User already registered: re-connection
strcpy(text, "L'utente era gia' registrato al servizio: riconnessione completata.\n"); //Re-connection completed
reg[i].status = 'c';
reg[i].address.sin_family = client.sin_family;
reg[i].address.sin_port = p;
reg[i].address.sin_addr.s_addr = client.sin_addr.s_addr;
length = strlen(text);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) text, length, 0);
if(rv < 0) {};
if(reg[i].msg > 0) { //messaggi offline
strcpy(text, "Messaggi offline presenti.\n"); //Offline messages found
length = strlen(text);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) text, length, 0);
if(rv < 0) {};
//Sending number of messages to be sent
length = sizeof(*last);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
l = htons(*last);
rv = send(sckt, (void*) &l, length, 0);
if(rv < 0) {};
for(j=0; j<reg[i].msg; j++) {
sprintf(buffer, "%s > ", reg[i].sender[j]);
strcat(buffer, reg[i].pendent[j]);
length = strlen(buffer);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) buffer, length, 0);
if(rv < 0) {};
};
//Set number of messages to send to 0
reg[i].msg = 0;
} else {
strcpy(text, "Nessun messaggio offline presente.\n"); //No offline messages
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) text, length, 0);
if(rv < 0) {};
};
return 1;
};
};
//If the user is not already registered
if(*last == MAX_UTN) { //max number of users reached
strcpy(text, "Impossibile registrarsi al servizio: numero limite di utenti raggiunto.\n"); //Max number of users reached
pos = -1;
} else {
strcpy(reg[*last].username, name);
reg[*last].address.sin_family = client.sin_family;
reg[*last].address.sin_port = p;
reg[*last].address.sin_addr.s_addr = client.sin_addr.s_addr;
reg[*last].status = 'c';
reg[*last].msg = 0;
(*last)++;
pos = 1;
};
length = strlen(text);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {}
rv = send(sckt, (void*) text, length, 0);
if(rv < 0) {}
return pos;
}
void srv_quit(int sckt, struct users* reg, char* user, int num) {
int i, length, l, rv;
char text[DIM];
memset(text, 0, DIM);
strcpy(text, "Utente disconnesso.\n"); //_User disconnected
for(i=0; i<num; i++) {
if(strcmp(reg[i].username, user) == 0) { //user actually registered to the service
if(reg[i].status == 'c') {
reg[i].status = 'o';
};
memset(®[i].address, 0, sizeof(reg[i].address));
length = strlen(text);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) text, length, 0);
if(rv < 0) {};
printf("%s disconnesso.\n", user); //<User> disconnected
return;
};
};
//if here, user is not registered to the service
strcpy(text, "L'utente non era registrato al servizio.\n"); //User not registered
length = strlen(text);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) text, length, 0);
if(rv < 0) {};
}
void srv_send(int sckt, struct users* reg, int num, char* dest, char* source) {
int i, rv, length, l;
char text[DIM];
char addr[ADDR_DIM];
memset(text, 0, DIM);
for(i=0; i<num; i++) {
if(strcmp(reg[i].username, dest) == 0) { //User registered
if(reg[i].status == 'c') { //user connected: provides destination UDP address to the sender (it will directly send the message)
inet_ntop(AF_INET, ®[i].address.sin_addr.s_addr, addr, sizeof(addr));
sprintf(text, "Client attualmente connesso: %s %d \n", addr , ntohs(reg[i].address.sin_port));
break;
} else { //user disconnected: save offline message
//Getting the message
rv = recv(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
length = ntohs(l);
rv = recv(sckt, (void*) reg[i].pendent, length, 0);
if(rv < 0) {};
reg[i].pendent[reg[i].msg][length] = '\0';
strcpy(reg[i].sender[reg[i].msg], source);
reg[i].msg++;
//Sending info to te sender
strcpy(text, "Messaggio salvato per l'invio offline.\n"); //Message saved offline
length = strlen(text);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) text, length, 0);
if(rv < 0) {};
return;
};
};
};
//Here if got into the if statement
length = strlen(text);
l = htons(length);
rv = send(sckt, (void*) &l, sizeof(l), 0);
if(rv < 0) {};
rv = send(sckt, (void*) text, length, 0);
if(rv < 0) {};
}
int main(int argc, char* argv[]) {
//shared (mapped) memory
struct users* registered = mmap(0, MAX_CONN*sizeof(struct users), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0);
//last index with user struct to be used
int* last = mmap(0, sizeof(int), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0);
int sd; //socket descriptor
int conn_sd; //socket descriptor after connect()
struct sockaddr_in my_addr;
struct sockaddr_in cl_addr;
int err; //for errors
int udp_port;
char check[NAME_DIM]; //will containg the username of the client connected
socklen_t len;
int pid;
int dim_rcvd_net, dim_rcvd, dim_sent_net, dim_sent;
char buffer[DIM];
char cmd[CMD_DIM];
char name[NAME_DIM];
char port[PORT_DIM];
*last = 0;
memset(registered, 0, MAX_CONN*sizeof(struct users));
memset(check,0, NAME_DIM);
puts("Avvio del servizio...\n"); //Service starting..
if(argc != 2) {
printf("Errore: troppi argomenti. \n Utilizzare solamente un argomento."); //Please use only one argument
exit(EXIT_FAILURE);
};
//Maybe check the argument itself?
sd = socket(AF_INET, SOCK_STREAM, 0);
memset(&my_addr, 0, sizeof(my_addr));
//Socket parameters
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(atoi(argv[1]));
my_addr.sin_addr.s_addr = INADDR_ANY;
err = bind(sd, (struct sockaddr*) &my_addr, sizeof(my_addr));
if(err < 0) {};
err = listen(sd, MAX_CONN);
if(err < 0) {};
puts("Servizio attivo.\n"); //Service activated
//Concurrent server
while(1) {
len = sizeof(my_addr);
conn_sd = accept(sd, (struct sockaddr*) &cl_addr, &len);
//error check to be done
pid = fork();
if(pid == 0) {
//Child
close(sd);
while(1) {
//Command dimension
err = recv(conn_sd, (void*) &dim_rcvd_net, sizeof(dim_rcvd), 0);
if(err < 0) {};
dim_rcvd = ntohs(dim_rcvd_net);
//Command
err = recv(conn_sd, (void*) buffer, dim_rcvd, 0);
if(err < 0) {};
buffer[dim_rcvd] = '\0';
sscanf(buffer, "%s", cmd);
if(strcmp(cmd, "!help") == 0) {
srv_help(conn_sd);
};
if(strcmp(cmd, "!register") == 0) {
if(strlen(check) > 0) { //Already connected with another username
puts("Sei già connesso con altro nome.\n"); //Already connected
} else {
sscanf(buffer, "%s %s %s", cmd, name, port);
udp_port = atoi(port);
if(srv_register(conn_sd, registered, name, cl_addr, udp_port, last) == 1) {
strcpy(check, name);
};
};
};
if(strcmp(cmd, "!deregister") == 0) {
if(strlen(check) <= 0) { //if not registered
strcpy(buffer, "Devi essere connesso per poter utilizzare questa funzione.\n"); //You have to be registered
dim_sent = strlen(buffer);
dim_sent_net = htons(dim_sent);
err = send(conn_sd, (void*) &dim_sent_net, sizeof(dim_sent_net), 0);
if(err < 0) {};
err = send(conn_sd, (void*) buffer, dim_sent, 0);
if(err < 0) {};
} else {
srv_deregister(conn_sd, registered, check, last);
strcpy(check, "");
};
};
if(strcmp(cmd, "!send") == 0) {
if(strlen(check) <= 0) { //if not registered
strcpy(buffer, "Devi essere connesso per poter utilizzare questa funzione.\n"); //You have to be registered
dim_sent = strlen(buffer);
dim_sent_net = htons(dim_sent);
err = send(conn_sd, (void*) &dim_sent_net, sizeof(dim_sent_net), 0);
if(err < 0) {};
err = send(conn_sd, (void*) buffer, dim_sent, 0);
if(err < 0) {};
} else {
sscanf(buffer, "%s %s", cmd, name);
srv_send(conn_sd, registered, *last, name, check);
};
};
if(strcmp(cmd, "!who") == 0) {
if(strlen(check) <= 0) { //if not registered
strcpy(buffer, "Devi essere connesso per poter utilizzare questa funzione"); //You have to be registered
dim_sent = strlen(buffer);
dim_sent_net = htons(dim_sent);
err = send(conn_sd, (void*) &dim_sent_net, sizeof(dim_sent_net), 0);
if(err < 0) {};
err = send(conn_sd, (void*) buffer, dim_sent, 0);
if(err < 0) {};
} else {
srv_who(conn_sd, registered, *last);
};
};
if(strcmp(cmd, "!quit") == 0) {
srv_quit(conn_sd, registered, check, *last);
close(conn_sd);
exit(EXIT_SUCCESS);
};
};
} else {
//Parent
close(conn_sd);
};
};
close(sd);
return 0;
}
编辑2
有件事我不明白。我刚刚重新执行了粘贴在这里的完全相同的程序,它似乎正确地发送了消息(目前仅在线)。
可能是同步问题吗?
编辑3
以下是作业内容:
http://www2.ing.unipi.it/c.vallati/files/reti/Progetto2017.pdf
正如我在评论中所说,这是意大利语。。