gpt4 book ai didi

c - c语言的多线程客户端-服务器聊天应用程序

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:29:19 25 4
gpt4 key购买 nike

我编写了一个用于在两个客户端之间进行通信的应用程序(一个将运行 server.c 应用程序,另一个将运行 client.c)。至此一切顺利,双方(client和server)都可以发送和接收消息了(双方有两个进程:一个是监听和打印消息,一个是接收和发送消息)。

到目前为止我得到的是:

客户端.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <signal.h>

#include "aes.h"

#define BSIZE 320

uint8_t key[] = "qwertyuioplkjhg";
uint8_t iv[] = "123456789098765";

void error(const char *msg) {
perror(msg);
exit(0);
}

int main(int argc, char *argv[]) {
int sockfd, portno, n, pid;
struct sockaddr_in serv_addr;
struct hostent *server;

char buffer[BSIZE];
char paddedData[BSIZE];
unsigned char crypted_data[BSIZE];

if (argc < 3) {
fprintf(stderr,"usage %s <hostname> <port>\n", argv[0]);
exit(0);
}

portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);

if (sockfd < 0) {
error("ERROR opening socket");
}

server = gethostbyname(argv[1]);

if (server == NULL) {
fprintf(stderr, "ERROR, no such host\n");
exit(0);
}

bzero((char *) &serv_addr, sizeof(serv_addr));

serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno);

if(connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) {
error("ERROR connecting");
}

//while(1) {
switch(pid = fork()) {
case -1:
error("ERROR fork");
case 0:
while(1) {
//printf("Please enter the message: ");
bzero(buffer, BSIZE);
//printf("Message: ");
fgets(buffer, BSIZE - 1, stdin);

strncpy(paddedData, buffer, BSIZE);
AES128_CBC_encrypt_buffer(crypted_data, (unsigned char*)paddedData, BSIZE, key, iv);

n = write(sockfd, crypted_data, BSIZE - 1);

if(n < 0) {
error("ERROR writing to socket");
}
}
default:
while(1) {
//bzero(buffer,256);

n = read(sockfd, buffer, BSIZE - 1);

AES128_CBC_decrypt_buffer((unsigned char*)paddedData, (unsigned char*)buffer, BSIZE, key, iv);

if(n < 0) {
error("ERROR reading from socket");
}

printf("<<server>>: %s", paddedData);
}
}

close(sockfd);

return 0;
}

和server.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include "aes.h"
#define BSIZE 320

uint8_t key[] = "qwertyuioplkjhg";
uint8_t iv[] = "123456789098765";

int numberOfConnections = 0;

void communications_handler(int);

void error(const char *msg) {
perror(msg);
exit(1);
}

int main(int argc, char *argv[]) {
int sockfd, newsockfd, portno, pid;
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);

while(1) {
/* [1] */
newsockfd = accept(sockfd, (struct sockaddr*)&cli_addr, &clilen);
numberOfConnections++;
printf("\nThere are %d clients connected!\n\n", numberOfConnections);

if (newsockfd < 0) {
error("ERROR on accept");
}

pid = fork();

if (pid < 0) {
error("ERROR on fork");
}

if (pid == 0) {
close(sockfd);
communications_handler(newsockfd);
exit(0);
}

else {
close(newsockfd);
}
}

close(sockfd);

return 0;
}

void communications_handler(int sock) {
int n, pid;
char buffer[BSIZE];
char paddedData[BSIZE];
unsigned char crypted_data[BSIZE];

switch(pid = fork()) {
case -1:
error("ERROR on fork");
case 0:
while(1) {
n = read(sock, buffer, BSIZE - 1);

AES128_CBC_decrypt_buffer((unsigned char*)paddedData, (unsigned char*)buffer, BSIZE, key, iv);

if(n < 0) {
error("ERROR reading from socket");
}

printf("<<client>>: %s", paddedData);
}
default:
while(1) {
bzero(buffer, BSIZE);
//printf("Message: ");
fgets(buffer, BSIZE - 1, stdin);

strncpy(paddedData, buffer, BSIZE);
AES128_CBC_encrypt_buffer(crypted_data, (unsigned char*)paddedData, BSIZE, key, iv);

for(int i = 0; i < numberOfConnections; i++) {
n = write(sock, crypted_data, BSIZE - 1);
}

if(n < 0) {
error("ERROR writing to socket");
}
}
}
}

现在我想通过让服务器接受多个连接来扩展这个程序(我实际上是这样做的,在 server.c 中 [1])。

但现在有一个问题:如何实现两个(或多个)客户端之间的通信(服务器只接受新连接,从所有连接的客户端读取数据,并将数据发送回所有客户端)。

这可以通过流程来完成吗?

最佳答案

查看 Beej 的非阻塞套接字编程指南:http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#select

关于c - c语言的多线程客户端-服务器聊天应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30000451/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com