不爱学习的那谁 的学生作业:
【图片】
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LOGIN_SUCCESS 1
#define LOGIN_FAILURE 0
typedef struct
{
char *ip;
unsigned char flag;
struct sockaddr_in peer_addr;
} thread_type;
void recv_data(int new_sockfd, struct sockaddr_in *client_addr)
{
int n = 0;
char buf[1024] = {0};
socklen_t len = sizeof(struct sockaddr_in);
while(1)
{
memset(buf, 0, sizeof(buf));
n = recvfrom(new_sockfd, buf, sizeof(buf), 0, (struct sockaddr *)client_addr, &len);
if(n < 0)
{
perror("Fail to recvfrom");
break;
}
printf("============================\n");
printf("Recv from IP = %s\n", inet_ntoa(client_addr->sin_addr));
printf("Recv from Port = %d\n", ntohs(client_addr->sin_port));
printf("Recv %d bytes : %s\n", n, buf);
if(strncmp(buf, "quit", 4) == 0)
break;
}
close(new_sockfd);
}
int init_socket(const char *ip, const char *port)
{
int sockfd;
struct sockaddr_in my_addr;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd < 0)
{
perror("Fail to socket!");
exit(EXIT_FAILURE);
}
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(atoi(port));
my_addr.sin_addr.s_addr = inet_addr(ip);
if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
{
perror("Fail to bind");
exit(EXIT_FAILURE);
}
printf("wait recv data on %s:%s!\n", ip, port);
return sockfd;
}
void *message_thread(void *arg)
{
thread_type *packet = (thread_type *)arg;
int new_sockfd;
struct sockaddr_in server_addr;
socklen_t len = sizeof(struct sockaddr_in);
// 创建新的套接字用于通信
new_sockfd = init_socket(packet->ip, "0");
// 获取新套接字的地址信息(端口号)
getsockname(new_sockfd, (struct sockaddr *)&server_addr, &len);
printf("New thread using port: %d\n", ntohs(server_addr.sin_port));
// 发送登录成功响应
sendto(new_sockfd, &packet->flag, sizeof(packet->flag), 0,
(struct sockaddr *)&packet->peer_addr, sizeof(packet->peer_addr));
// 接收数据
recv_data(new_sockfd, &packet->peer_addr);
// 释放内存
free(packet->ip);
free(packet);
pthread_exit(NULL);
}
void user_login(const char *ip, const char *port)
{
int sockfd;
int n = 0;
char buf[20] = {0};
struct sockaddr_in client_addr;
socklen_t len = sizeof(client_addr);
unsigned char login_flag;
sockfd = init_socket(ip, port);
while(1)
{
memset(buf, 0, sizeof(buf));
n = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&client_addr, &len);
if(n < 0)
{
perror("Fail to recvfrom");
continue;
}
printf("Received key from %s:%d: %s\n",
inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port),
buf);
login_flag = (strncmp(buf, "root", 4) == 0) ? LOGIN_SUCCESS : LOGIN_FAILURE;
if(login_flag == LOGIN_SUCCESS)
{
pthread_t tid;
thread_type *packet = malloc(sizeof(thread_type));
packet->flag = login_flag;
packet->ip = strdup(ip);
memcpy(&packet->peer_addr, &client_addr, sizeof(client_addr));
if(pthread_create(&tid, NULL, message_thread, (void *)packet) == 0) {
pthread_detach(tid);
printf("Created thread for client %s:%d\n",
inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
} else {
free(packet->ip);
free(packet);
}
} else {
// 直接回复登录失败
sendto(sockfd, &login_flag, sizeof(login_flag), 0,
(struct sockaddr *)&client_addr, len);
printf("Login failed for client %s:%d\n",
inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
}
}
close(sockfd);
}
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;
}