【发布时间】:2016-05-24 17:23:44
【问题描述】:
我们得到了这段代码,并且应该修改它,以便每当客户端连接到服务器并发送消息时服务器应该回复我听到你的家伙。这适用于一个和多个客户端,但下一个任务是当一个新客户端连接时,服务器应该告诉所有其他连接的客户端。
我认为这会相当容易,但它并没有像我想象的那样奏效。由于服务器总是获得 sock 3 并且第一个客户端获得 4 并且第二个客户端获得 5 等等,所以我尝试制作一个 for 循环,每当新客户端连接时发送消息,循环将向 4,5 发送消息,这只是让服务器直接关闭自己.然后,我试图让当一个新客户端连接时,服务器应该向它实际执行的第一个客户端(4)发送消息,但只有当客户端(4)向服务器写入一条消息时,他才会收到服务器发送的广播。
所以看起来客户想要写,但需要在他收到来自服务器的广播之前写一些东西,任何帮助将不胜感激,因为我们是这一切的初学者。
这就是代码现在的样子。
服务器.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);
}
}
【问题讨论】:
标签: c sockets server pthreads client