史啦啦 的学生作业:
#include
#include
#include
#include
#include /* See NOTES */
#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 printf_client_info(struct sockaddr_in *addr,char *buf)
{
printf("===============================\n");
printf("user IP : %s\n",inet_ntoa(addr->sin_addr));
printf("user port : %d\n", ntohs(addr->sin_port));
printf("user data : %s\n",buf);
}
//1.初始化socket连接
int init_socket(const char *ip,const char *port)
{
int sockfd = 0;
struct sockaddr_in my_addr;
socklen_t len = sizeof(my_addr);
//1.通过socket创建文件描述符
sockfd = socket(AF_INET,SOCK_DGRAM ,0);
if(sockfd < 0)
{
perror("Fail to socket!");
exit(EXIT_FAILURE);
}
//2.填充服务器自己的ip地址和port,然后绑定
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,len) < 0)
{
perror("Fail to bind");
return -1;
}
return sockfd;
}
void recv_data(int new_sockfd)
{
int n = 0;
char buf[1024] = {0};
struct sockaddr_in client_addr;
socklen_t len = sizeof(client_addr);
//3.发送数据
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");
exit(EXIT_FAILURE);
}
printf_client_info(&client_addr,buf);
if(strncmp(buf,"quit",4) == 0)
break;
}
close(new_sockfd);
return ;
}
void *message_thread(void *arg)
{
thread_type *packet = (thread_type *)arg;
//1.给用户回复的秘钥正确信息
char *ip = packet->ip;
unsigned char login_flag = packet->flag;
struct sockaddr_in *addr = packet->peer_addr;
//创建套接字,获得用户数据,绑定0号端口,系统会随机分配一个可用的端口
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;
char buf[1024] = {0};
struct sockaddr_in client_addr;
socklen_t len = sizeof(client_addr);
unsigned char login_flag;
int sockfd;
thread_type packet;
pthread_t tid;
//1.创建套接字,获得用户数据
sockfd = init_socket(ip,port);
//2.接收登录数据
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");
exit(EXIT_FAILURE);
}
printf("key = %s\n",buf);
login_flag = (strncmp(buf,"root",4) == 0) ? LOGIN_SUCCESS : LOGIN_FAILURE;
//说明此时秘钥正确
if(login_flag == LOGIN_SUCCESS)
{
packet.ip = (char *)ip;
packet.flag = login_flag;
packet.peer_addr = &client_addr;
//创建子线程,子线程准备接收当前用户数据,主线程接续接收新用户的秘钥
pthread_create(&tid,NULL,message_thread,(void *)&packet);
}else{
//秘钥不正确,使用原始端口回复信息
sendto(sockfd,&login_flag,sizeof(login_flag),0,(struct sockaddr *)&client_addr,len);
}
//把线程设置为分离式,子线程结束后,系统会自动回收资源
pthread_detach(tid);
}
return ;
}
//./a.out ip port
int main(int argc, const char *argv[])
{
int sockfd;
unsigned char login_flag;
if(argc < 3)
{
fprintf(stderr,"Usage : %s ip port!\n",argv[0]);
exit(EXIT_FAILURE);
}
//1.接收用户的秘钥,准备登录
user_login(argv[1],argv[2]);
return 0;
}