我们得到了这个代码,并且应该对其进行修改,以便每当客户端连接到服务器并发送消息时,服务器应该回复我听到你的家伙。这适用于一个和多个客户端,但下一个任务是当新客户端连接服务器时应该告诉所有其他连接的客户端。
我认为这会相当容易,但它没有像我想的那样运作。由于服务器总是获得sock 3,第一个客户端获得4个,第二个客户端获得5个等等,我试图创建一个for循环,每当新客户端连接循环时就会发送消息,将消息发送到4,5只是让服务器直接关闭自己。然后,我尝试在新客户端连接时尝试发送服务器应该向第一个客户端(4)发送消息,但是只有当客户端(4)将消息写入服务器时,他才会收到服务器发送的广播。 / p>
所以看起来客户想写,但需要在收到服务器的广播之前写一些东西,任何帮助都会受到赞赏,因为我们对这一切都是初学者。
这就是代码目前的样子。
server.c
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/times.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <pthread.h>
#define PORT 5555
#define MAXMSG 512
void *connection_handler(void *socket_desc)
{
int sock = *(int*)socket_desc;
int read_size;
char *message, client_message[2000], *message_to_client;
message = "Greetings! I am your connection handler\n";
write(sock, message, strlen(message));
while( (read_size = recv(sock, client_message, 2000, 0)) > 0)
{
client_message[read_size] = '\0';
printf("Client[%d]: %s", sock, client_message);
message_to_client = "I hear you dude...";
write(sock, message_to_client, 19);
memset(client_message, 0, 2000);
}
if(read_size == 0)
{
printf("Client[%d] disconnected", sock);
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
free(socket_desc);
return 0;
}
int makeSocket(unsigned short int port) {
int sock;
struct sockaddr_in name;
/* Create a socket. */
sock = socket(PF_INET, SOCK_STREAM, 0);
if(sock < 0) {
perror("Could not create a socket\n");
exit(EXIT_FAILURE);
}
name.sin_family = AF_INET;
name.sin_port = htons(port);
name.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sock, (struct sockaddr *)&name, sizeof(name)) < 0) {
perror("Could not bind a name to the socket\n");
exit(EXIT_FAILURE);
}
return(sock);
}
int main(int argc, char *argv[])
{
int sock;
int clientSocket;
int i;
int *new_sock;
char *broadcast;
fd_set activeFdSet, readFdSet;
struct sockaddr_in clientName;
socklen_t size;
sock = makeSocket(PORT);
if(listen(sock,1) < 0)
{
perror("Could not listen for connections\n");
exit(EXIT_FAILURE);
}
FD_ZERO(&activeFdSet);
FD_SET(sock, &activeFdSet);
while(1)
{
printf("Waiting for connections\n");
readFdSet = activeFdSet;
if(select(FD_SETSIZE, &readFdSet, NULL, NULL, NULL) < 0)
{
perror("Select failed\n");
exit(EXIT_FAILURE);
}
for(i = 0; i < FD_SETSIZE; ++i)
{
if(FD_ISSET(i, &readFdSet))
{
if(i == sock)
{
size = sizeof(struct sockaddr_in);
pthread_t sniffer_thread;
while(( clientSocket = accept(sock, (struct sockaddr *)&clientName, (socklen_t *)&size)))
{
puts("Connection accepted");
new_sock = malloc(1);
*new_sock = clientSocket;
if( pthread_create( &sniffer_thread, NULL, connection_handler, (void*) new_sock) < 0)
{
perror("could not create thread");
return 1;
}
broadcast = "NEW CLIENT CONNECTED";
write(4, broadcast, sizeof(broadcast)); //just to see if when ever a new client connects the first client should get all these messages
write(4, broadcast, sizeof(broadcast));
write(4, broadcast, sizeof(broadcast));
pthread_detach(sniffer_thread);
puts("Handler assigned");
FD_SET(*new_sock, &activeFdSet);
}
if(clientSocket < 0)
{
perror("Could not accept connection\n");
exit(EXIT_FAILURE);
}
}
else
{
if(readMessageFromClient(i) < 0)
{
close(i);
FD_CLR(i, &activeFdSet);
}
}
}
}
}
}
对于客户端,代码看起来像这样
client.c
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define PORT 5555
#define hostNameLength 50
#define messageLength 256
void initSocketAddress(struct sockaddr_in *name, char *hostName, unsigned short int port)
{
struct hostent *hostInfo;
name->sin_family = AF_INET;
name->sin_port = htons(port);
hostInfo = gethostbyname(hostName);
if(hostInfo == NULL)
{
fprintf(stderr, "initSocketAddress - Unknown host %s\n",hostName);
exit(EXIT_FAILURE);
}
name->sin_addr = *(struct in_addr *)hostInfo->h_addr;
}
void writeMessage(int fileDescriptor, char *message)
{
int nOfBytes;
nOfBytes = write(fileDescriptor, message, strlen(message) + 1);
if(nOfBytes < 0)
{
perror("writeMessage - Could not write data\n");
exit(EXIT_FAILURE);
}
}
int main(int argc, char *argv[])
{
int sock;
struct sockaddr_in serverName;
char hostName[hostNameLength];
char messageString[messageLength];
char buffer[1024];
if(argv[1] == NULL)
{
perror("Usage: client [host name]\n");
exit(EXIT_FAILURE);
}
else
{
strncpy(hostName, argv[1], hostNameLength);
hostName[hostNameLength - 1] = '\0';
}
sock = socket(PF_INET, SOCK_STREAM, 0);
if(sock < 0)
{
perror("Could not create a socket\n");
exit(EXIT_FAILURE);
}
initSocketAddress(&serverName, hostName, PORT);
if(connect(sock, (struct sockaddr *)&serverName, sizeof(serverName)) < 0)
{
perror("Could not connect to server\n");
exit(EXIT_FAILURE);
}
printf("\nType something and press [RETURN] to send it to the server.\n");
printf("Type 'quit' to nuke this program.\n");
fflush(stdin);
recv(sock, buffer, 1024, 0);
printf(buffer);
while(1)
{
printf("\n>");
fgets(messageString, messageLength, stdin);
messageString[messageLength - 1] = '\0';
if(strncmp(messageString, "quit\n",messageLength) != 0)
writeMessage(sock, messageString);
if(recv(sock, buffer, 1024, 0) > 0)
printf(buffer);
}
}
答案 0 :(得分:2)
您需要对代码进行一些更改才能使其正常运行。你没有收到任何东西的原因是你的客户被困在
fgets(messageString,messageLength,stdin);这是一个阻塞调用,所以只需在客户端创建一个消息接收线程,以便它可以连续监听。对代码进行以下更改,它可以帮助您实现结果。
将以下行添加到客户端代码:
client.c
void * receiveMessage(void * socket)
{
int sockfd, ret;
char buffer[1024];
sockfd = (int) socket;
int count = 1;
memset(buffer, 0, 1024);
for (;;)
{
if (recvfrom(sockfd, buffer, 1024, 0, NULL, NULL) > 0)
{
fputs(buffer, stdout);
printf("\n");
}
}
}
在main函数中添加以下行
//creating a new thread for receiving messages from the server
read = pthread_create(&rThread, NULL, receiveMessage, (void *) sock);
if (read < 0)
{
printf("ERROR: Return Code from pthread_create() is %d\n", read);
exit(1);
}
并将while循环更改为
while(1)
{
printf("\n>");
fgets(messageString, messageLength, stdin);
messageString[messageLength - 1] = '\0';
if(strncmp(messageString, "quit\n",messageLength) != 0)
{
writeMessage(sock, messageString);
}
}
Server.c(在连接处理程序中添加广播消息)
void *connection_handler(void *socket_desc)
{
int sock = *(int*)socket_desc;
int read_size;
char *message, client_message[2000], *message_to_client;
char broadcast[50] = "new client connected";
int num;
num = sock;
num--;
while(num > 3)
{
write(num, broadcast, strlen(broadcast));
sleep(1);
num--;
}
while((read_size = recv(sock, client_message, 2000, 0)) > 0)
{
client_message[read_size] = '\0';
printf("Client[%d]: %s", sock, client_message);
message_to_client = "I hear you dude...";
write(sock, message_to_client, strlen(message_to_client));
memset(client_message, 0, 2000);
}
if(read_size == 0)
{
printf("Client[%d] disconnected", sock);
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
free(socket_desc);
return 0;
}