我想构建一个聊天程序,但问题是,一旦客户端发送消息到服务器,所有其他客户端将收到此消息从服务器,但客户端不不知道什么时候会有消息。在客户端的主循环中,它将阻塞fgets()并等待用户输入命令或消息。我需要客户端程序来接收消息并在等待用户输入时进行打印。我怎样才能做到这一点 ?c TCP聊天程序,客户端不知道何时recv
这里是代码: 我还没有写recv消息,因为我不知道该把它放在哪里。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <time.h>
#define LOGIN 1
#define LO_ACK 2
#define LO_NACK 3
#define EXIT 4
#define JOIN 5
#define JN_ACK 6
#define JN_NACK 7
#define LEAVE_SESS 8
#define NEW_SESS 9
#define NS_ACK 10
#define MESSAGE 11
#define QUERY 12
#define QU_ACK 13
struct packet {
unsigned int type;
unsigned int size;
char source[20];
char data[500];
};
int encode(struct packet temp, char *data) {
sprintf(data, "%d:%d:%s:", temp.type, temp.size,
temp.source);
int length = strlen(data);
int i;
for (i = 0; i < temp.size; i++) {
data[length + i] = temp.data[i];
}
data[length + i] = '\0';
return length;
}
struct packet decode(char *data) {
int i, j;
struct packet message;
char temp[100];
char source[20];
sscanf(data, "%d:%d", &message.type, &message.size);
sprintf(temp, "%d:%d", message.type, message.size);
int length = strlen(temp);
for (i = length + 1; data[i] != ':'; i++) {
message.source[i - length - 1] = data[i];
}
for (j = 0; j < message.size; j++) {
message.data[j] = data[j + i + 1];
}
return message;
}
int main(void) {
int sockfd, numbytes;
struct addrinfo hints, *servinfo, *p;
int rv;
int login = 0;
char me[20];
while (1) {
char buf[500];
char input[100];
char *command;
char arg1[20], arg2[20], arg3[20], arg4[20], arg5[20];
int i, j, k, l, m;
fgets(input, 100, stdin);
if (strlen(input) < 3)
continue;
if (input[0] == '/') {//command
command = &input[1];
//get first argument
for (i = 0; command[i] != '\0' && command[i] != ' '; i++) {
arg1[i] = command[i];
}
//arg1[i] = '\0';
if (strcmp(arg1, "login") == 0) {//login
//get id,password,ip,port
if (login == 1) {
printf("error: already login\n");
continue;
}
for (j = i + 1; command[j] != '\0' && command[j] != ' '; j++) {//id
arg2[j - i - 1] = command[j];
}
//arg1[j-i+1] = '\0';
for (k = j + 1; command[k] != '\0' && command[k] != ' '; k++) {//password
arg3[k - j - 1] = command[k];
}
for (l = k + 1; command[l] != '\0' && command[l] != ' '; l++) {//ip
arg4[l - k - 1] = command[l];
}
for (m = l + 1; command[m] != '\0'; m++) {//port
arg5[m - l - 1] = command[m];
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((rv = getaddrinfo(arg4, arg5, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
for (p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("client: socket");
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("client: connect");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "client: failed to connect\n");
return 2;
}
freeaddrinfo(servinfo);
struct packet tosend;
tosend.type = LOGIN;
sprintf(tosend.data, "%s %s", arg2, arg3);
strcpy(tosend.source, arg2);
tosend.size = strlen(tosend.data);
char message[500];
encode(tosend, message);
send(sockfd, message, strlen(message), 0);
usleep(100);
recv(sockfd, buf, strlen(buf), 0);
struct packet reply;
reply = decode(buf);
if (reply.type == LO_ACK) {
printf("login successful\n");
strcpy(me, arg2);
login = 1;
continue;
} else if (reply.type == LO_NACK) {
printf("login failed: %s\n", reply.data);
continue;
}
} else if (strcmp(arg1, "createsession") == 0) {
if (login == 0) {
printf("error: not login\n");
continue;
}
for (j = i + 1; command[j] != '\0'; j++) {//session name
arg2[j - i - 1] = command[j];
}
struct packet tosend;
tosend.type = NEW_SESS;
strcpy(tosend.data, arg2);
strcpy(tosend.source, me);
tosend.size = strlen(tosend.data);
char message[500];
encode(tosend, message);
send(sockfd, message, strlen(message), 0);
usleep(100);
recv(sockfd, buf, strlen(buf), 0);
struct packet reply;
reply = decode(buf);
if (reply.type == NS_ACK) {
printf("create session successful\n");
continue;
} else if (reply.type == JN_ACK) {
printf("session already exist, join session successful\n");
continue;
}
} else if (strcmp(arg1, "joinsession") == 0) {
if (login == 0) {
printf("error: not login\n");
continue;
}
for (j = i + 1; command[j] != '\0'; j++) {//session name
arg2[j - i - 1] = command[j];
}
struct packet tosend;
tosend.type = JOIN;
strcpy(tosend.data, arg2);
strcpy(tosend.source, me);
tosend.size = strlen(tosend.data);
char message[500];
encode(tosend, message);
send(sockfd, message, strlen(message), 0);
usleep(100);
recv(sockfd, buf, strlen(buf), 0);
struct packet reply;
reply = decode(buf);
if (reply.type == JN_ACK) {
printf("join session successful\n");
continue;
}
} else if (strcmp(arg1, "leavesession") == 0) {
if (login == 0) {
printf("error: not login\n");
continue;
}
struct packet tosend;
tosend.type = LEAVE_SESS;
strcpy(tosend.data, "none");
strcpy(tosend.source, me);
tosend.size = strlen(tosend.data);
char message[500];
encode(tosend, message);
send(sockfd, message, strlen(message), 0);
printf("leave session successful\n");
continue;
} else if (strcmp(arg1, "list") == 0) {
if (login == 0) {
printf("error: not login\n");
continue;
}
struct packet tosend;
tosend.type = QUERY;
strcpy(tosend.data, "none");
strcpy(tosend.source, me);
tosend.size = strlen(tosend.data);
char message[500];
encode(tosend, message);
send(sockfd, message, strlen(message), 0);
usleep(100);
recv(sockfd, buf, strlen(buf), 0);
struct packet reply;
reply = decode(buf);
printf("%s", reply.data);
continue;
} else {
printf("invalid command\n");
continue;
}
} else {//message
if (login == 0) {
printf("error: not login\n");
continue;
}
struct packet tosend;
tosend.type = MESSAGE;
strcpy(tosend.data, input);
strcpy(tosend.source, me);
tosend.size = strlen(tosend.data);
char message[500];
encode(tosend, message);
send(sockfd, message, strlen(message), 0);
continue;
}
}
}
这不是如何工作。你不能要求我们为你写代码。显示你的努力。如果您提交代码,我们只能提供帮助。 – Arvindsinc2
哪里?...请发布代码 – Arvindsinc2
有两种选择。 1)线程2)选择。我们必须留给您阅读,并尝试为他们编写*代码*。 –