我试图在c中编写一个服务器,允许连接的客户端相互发送消息。我尝试通过接收消息,将其放在队列上并让处理服务器 - 客户端通信(函数dostuff)的进程在用户名与消息匹配时传递该消息。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
/******Struct msg*********/
typedef struct msg
{
char dest [64];
char origin[64];
char text [256];
}msg;
/*********Queue*********/
/*Queue - Linked List implementation*/
#include<stdio.h>
#include<stdlib.h>
struct Node {
msg *data;
struct Node* next;
};
struct Node* front = NULL;
struct Node* rear = NULL;
void Enqueue(msg *x) {
struct Node* temp =
(struct Node*)malloc(sizeof(struct Node));
temp->data =x;
temp->next = NULL;
if(front == NULL && rear == NULL){
front = rear = temp;
return;
}
rear->next = temp;
rear = temp;
}
void Dequeue() {
struct Node* temp = front;
if(front == NULL) {
printf("Queue is Empty\n");
return;
}
if(front == rear) {
front = rear = NULL;
}
else {
front = front->next;
}
free(temp);
}
msg *Front() {
if(front == NULL) {
return 0;
}
return front->data;
}
void error(const char *msg)
{
perror(msg);
exit(1);
}
int interpret(char *line, char username[])
{
//printf("Ready to interpret: %s\n",line);
/*
char *command, *arg1 , *arg2,l[64];
msg *message;
strcpy(l,line);
command = strtok(l," ");
if(strcmp(command, "/tell") == 0)
{
printf("The command was vaid!\n");//chegou aqui
printf("Ready to interpret: %s\n",l);
arg1 = strtok(NULL," ");
printf("I got this far!");
arg2 = l + strlen(command) + strlen(arg1) + 2; //somamos dois por causa dos espaços
message = (msg*)malloc(sizeof(msg));
//printf("I got this far!"); nao está a chegar aqui
strcmp(message->dest, arg1);
strcmp(message->origin, username);
strcmp(message->text, arg2);
Enqueue(message);
printf("(%s -> %s) -%s- was placed on the queue",message->origin,message->dest,message->text);
}
else
{
printf("comando inválido");
}
*/
//this is temporary because there is an error with the code above which made the message not be correct
msg *message;
message = (msg*)malloc(sizeof(msg));
strcmp(message->dest, "dest");
strcmp(message->origin, "origin");
strcmp(message->text, "blahblahblah");
Enqueue(message);
return 1;
}
void dostuff (int sock, char username[])
{
int n, pid;
char buffer[256], dest[64];
pid = fork();
while(1)
{
if(pid > 0)
{
bzero(buffer,256);
n = read(sock,buffer,255);
if (n < 0) error("ERROR reading from socket");
printf("Here is the full message: %s\n",buffer);
//n = write(sock,"I got your message!\n",18);
//if (n < 0) error("ERROR writing to socket");
interpret(buffer, username);
}
else
{
sleep(1);
if(Front() != NULL)
{
strcpy(dest, Front()->dest);
if(strcmp(dest, username) == 0)
{
strcpy(buffer, Front()->text);
Dequeue();
n = write(sock,buffer,strlen(buffer));
if (n < 0) error("ERROR writing to socket");
}
}
}
}
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, pid , f;
int userCount;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
if (argc < 2)
{
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
userCount = 0;
char dname[64];
f = fork();
while (1)
{
if(f > 0)
{
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) error("ERROR on accept");
userCount++;
sprintf(dname, "%d", userCount);
pid = fork();
if (pid < 0) error("ERROR on fork");
if (pid == 0)
{
close(sockfd);
dostuff(newsockfd, dname);
exit(0);
}
else close(newsockfd);
}
}
close(sockfd);
return 0;
}
问题似乎是这段代码应该从队列中删除项目:
if(Front() != NULL)
{
strcpy(dest, Front()->dest);
if(strcmp(dest, username) == 0)
{
strcpy(buffer, Front()->text);
Dequeue();
n = write(sock,buffer,strlen(buffer));
if (n < 0) error("ERROR writing to socket");
}
}
永远不会被运行。 我之前从未做过这样的事情,所以这种做法可能完全错了。如果有人可以向我解释我做错了什么,或者提出了不同的解决方案,那就太棒了。
答案 0 :(得分:0)
您误解了fork()
之后管理全局变量的方式。
他们没有被分享;进程可以修改自己的变量副本。这些修改不会通知其他孩子/父母。
因此,您尝试使用Enqueue
进行更改front
指针的本地副本,但前指针的其他子副本不会更新。
将代码降至最低:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
/******Struct msg*********/
typedef struct msg
{
char dest [64];
char origin[64];
char text [256];
}msg;
/*********Queue*********/
/*Queue - Linked List implementation*/
#include<stdio.h>
#include<stdlib.h>
struct Node {
msg *data;
struct Node* next;
};
struct Node* front = NULL;
struct Node* rear = NULL;
void Enqueue(msg *x)
{
struct Node* temp = malloc(sizeof(struct Node));
temp->data =x;
temp->next = NULL;
if(front == NULL && rear == NULL)
{
front = rear = temp;
printf("front: %p\n", (void *)(front));
printf("rear: %p\n" , (void *)(rear));
printf("temp: %p\n" , (void *)(temp));
return;
}
rear->next = temp;
rear = temp;
}
void Dequeue(void) {
struct Node* temp = front;
if(front == NULL) {
printf("Queue is Empty\n");
return;
}
if(front == rear) {
front = rear = NULL;
}
else {
front = front->next;
}
free(temp);
}
msg *Front(void) {
if(front == NULL) {
return 0;
}
return front->data;
}
void error(const char *msg)
{
perror(msg);
exit(1);
}
int interpret(void)
{
//this is temporary because there is an error with the code above which made the message not be correct
msg *message;
message = (msg*)malloc(sizeof(msg));
strcpy(message->dest, "dest");
strcpy(message->origin, "origin");
strcpy(message->text, "blahblahblah");
Enqueue(message);
return 1;
}
void dostuff (void)
{
pid_t pid;
pid = fork();
if(pid > 0)
{
interpret();
}
else
{
sleep(1);
printf("\nfront: %p\n", (void *)(front));
}
}
int main(int argc, char *argv[])
{
pid_t f, pid;
f = fork();
if(f > 0)
{
pid = fork();
if (pid < 0)
error("ERROR on fork");
if (pid == 0)
{
dostuff();
}
}
return 0;
}
输出
front: 0x18371a0
rear: 0x18371a0
temp: 0x18371a0
root@mypc:~$
front: (nil)
答案 1 :(得分:0)
使用线程而不是fork。 开始两个线程。一个用于倾听,一个用于回答。
Fork创建了新的操作系统进程,它共享相同的代码,但数据段不同。所以你在一个过程中改变的东西将不会出现在另一个过程中。