weixin_慕哥3021856 的学生作业:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LOGIN_SUCCESS 1
#define LOGIN_FAILURE 0
typedef struct{
const char *ip;
unsigned char flag;
struct sockaddr_in *peer_addr;
}thread_type;
int init_socket(const char *ip, const char *port)
{
int sockfd = 0;
struct sockaddr_in saddr; // server addr
socklen_t len = sizeof(saddr);
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
perror("socket failed.\n");
exit(EXIT_FAILURE);
}
// 填充服务器自身的IP和端口号
memset(&saddr, 0 , sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = inet_addr(ip);
saddr.sin_port = htons(atoi(port));
if (bind(sockfd, (struct sockaddr *)&saddr, len) < 0)
{
perror("bind failed.\n");
exit(EXIT_FAILURE);
}
printf("Wait to receive data...\n");
return sockfd;
}
void printf_client_info(struct sockaddr_in *addr, char *buffer)
{
printf("--------------------\n");
printf("Recv from ip: %s\n", inet_ntoa(addr->sin_addr));
printf("Recv from port: %d\n", ntohs(addr->sin_port));
printf("Recv data: %s\n", buffer);
}
void recv_data(int sockfd)
{
int n = 0;
char buf[1024] = {0};
struct sockaddr_in client_addr;
socklen_t len = sizeof(client_addr);
while (1)
{
memset(buf, 0, sizeof(buf));
n = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&client_addr, &len);
if (n < 0)
{
perror("[ERROR] recvfrom()");
exit(EXIT_FAILURE);
}
if (strncmp(buf, "quit", 4) == 0)
{
printf("\nBye!\n");
break;
}
printf_client_info(&client_addr, buf);
}
close(sockfd);
return ;
}
void *message_thread(void *arg)
{
// 服务端在密钥正确时回复的信息
thread_type *packet = (thread_type *)arg;
const char *ip = packet->ip;
unsigned char login_flag = packet->flag;
struct sockaddr_in *addr = packet->peer_addr;
// 创建新的套接字和端口用于通信
int new_sockfd = init_socket(ip, "0");
sendto(new_sockfd, &login_flag, sizeof(login_flag), 0, (struct sockaddr *)addr, sizeof(struct sockaddr_in));
// 接收数据
recv_data(new_sockfd);
pthread_exit(NULL);
}
void user_login(const char *ip, const char *port)
{
int n = 0;
int sockfd, ptsockfd; // pthread new sockfd
char buf[32] = {0};
unsigned char login_flag;
struct sockaddr_in caddr; // client addr
socklen_t len = sizeof(caddr);
pthread_t tid;
thread_type packet;
// get socket
sockfd = init_socket(ip, port);
while (1)
{
memset(buf, 0, sizeof(buf));
n = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&caddr, &len);
if (n < 0)
{
perror("[ERROR] recvfrom()");
exit(EXIT_FAILURE);
}
printf("Your key is %s\n", buf);
login_flag = (strncmp(buf, "root", 4) == 0)? LOGIN_SUCCESS: LOGIN_FAILURE;
// 密钥正确
if (login_flag == LOGIN_SUCCESS)
{
packet.ip = ip;
packet.flag = login_flag;
packet.peer_addr = &caddr;
printf("login successfully!\n");
// 创建子线程,子线程准备接收当前用户的数据,主线程负责接收用户的密钥
int err = pthread_create(&tid, NULL, message_thread, (void *)&packet);
if (err != 0)
{
fprintf(stderr, "[ERROR] pthread_create(): %s\n", strerror(err));
exit(EXIT_FAILURE);
}
}
else
{
// 给客户端回复登录失败
sendto(sockfd, &login_flag, sizeof(login_flag), 0, (struct sockaddr *)&caddr, len);
}
// 待系统自动回收线程,把线程设置为分离式
pthread_detach(tid);
}
return ;
}
int main(int argc, const char *argv[])
{
if (argc != 3)
{
fprintf(stderr, "Usage: %s ip port\n", argv[0]);
exit(EXIT_FAILURE);
}
// 验证密钥,执行用户登录
user_login(argv[1], argv[2]);
return 0;
}
【图片】