慕工程6300203 的学生作业:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LOGIN_SUCCESS 1
#define LOGIN_FAILURE 0
typedef struct
{
char *ip;
int login_flag;
struct sockaddr_in peer_addr;
} pthread_argv_t;
void recv_data(int fd)
{
char buffer[1024] = {0};
struct sockaddr_in client_addr;
socklen_t len = sizeof(client_addr);
int ret = 0;
while(1)
{
memset(buffer, 0, sizeof(buffer));
ret = recvfrom(fd, buffer, sizeof(buffer), 0, (struct sockaddr *)&client_addr, &len);
if (ret < 0)
{
perror("[ERROR] recvfrom");
exit(EXIT_FAILURE);
}
printf("============================\n");
printf("Recvfrom IP: %s\n", inet_ntoa(client_addr.sin_addr));
printf("Recvfrom PORT: %d\n", ntohs(client_addr.sin_port));
printf("Received data: %s\n", buffer);
if (strncmp(buffer, "quit", 4) == 0)
break;
}
close(fd);
}
int init_socket(char *ip, char *port)
{
int socket_fd;
struct sockaddr_in connect_addr;
int ret;
socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
if(socket_fd == -1)
{
perror("[ERROR] Socket Create Failed");
exit(EXIT_FAILURE);
}
memset(&connect_addr, 0, sizeof(connect_addr));
connect_addr.sin_family = AF_INET;
connect_addr.sin_port = htons(atoi(port));
connect_addr.sin_addr.s_addr = inet_addr(ip);
ret = bind(socket_fd, (struct sockaddr *)&connect_addr, sizeof(connect_addr));
if (ret < 0)
{
perror("[ERROR] Bind Failed");
exit(EXIT_FAILURE);
}
return socket_fd;
}
void *thread_func(void *arg)
{
pthread_argv_t *pthread_argv = (pthread_argv_t *)arg;
char *ip = pthread_argv->ip;
struct sockaddr_in client_addr = pthread_argv->peer_addr;
int login_flag = pthread_argv->login_flag;
int len = sizeof(client_addr);
int new_socket_fd = init_socket(ip,"0");
sendto(new_socket_fd, &login_flag, sizeof(login_flag), 0, (struct sockaddr *)&client_addr, len);
recv_data(new_socket_fd);
pthread_exit(NULL);
}
void user_login(char *ip, char *port)
{
int socket_fd;
// 这里原本定义指针,到thread_func中后,由于user_login已经结束,
// 这个局部变量失效了,导致服务端发送登录成功消息时,客户端无法接收到信息
struct sockaddr_in client_addr;
int len = sizeof(client_addr);
int ret = 0;
pthread_t tid;
pthread_argv_t pthread_argv;
char buffer[1024] = {0};
int login_flag = LOGIN_FAILURE;
socket_fd = init_socket(ip, port);
printf("wait for login\n");
while(1)
{
memset(buffer, 0, sizeof(buffer));
ret = recvfrom(socket_fd, buffer, sizeof(buffer), 0, (struct sockaddr *)&client_addr, &len);
if (ret < 0)
{
perror("[ERROR] Recv Failed");
exit(EXIT_FAILURE);
}
printf("key = %s\n", buffer);
login_flag = strncmp(buffer, "password", 8) == 0 ? LOGIN_SUCCESS : LOGIN_FAILURE;
if (login_flag == LOGIN_SUCCESS)
{
pthread_argv.login_flag = login_flag;
pthread_argv.ip = ip;
pthread_argv.peer_addr = client_addr;
pthread_create(&tid, NULL, thread_func, &pthread_argv);
} else
{
sendto(socket_fd, &login_flag, sizeof(login_flag), 0, (struct sockaddr *)&client_addr, len);
}
pthread_detach(tid);
}
}
int main(int argc, char* argv[])
{
if(argc != 3)
{
printf("Usage : %s \n", argv[0]);
exit(EXIT_FAILURE);
}
user_login(argv[1], argv[2]);
return 0;
}