北城半夏4806197 的學(xué)生作業(yè):
serve.c
#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創(chuàng)建文件描述符
sockfd = socket(AF_INET,SOCK_DGRAM ,0);
if(sockfd < 0)
{
perror("Fail to socket!");
exit(EXIT_FAILURE);
}
//2.填充服務(wù)器自己的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.發(fā)送數(shù)據(jù)
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;
char *ip = packet->ip;
unsigned char login_flag = packet->flag;
struct sockaddr_in *addr = packet->peer_addr;
//創(chuàng)建套接字,獲得用戶數(shù)據(jù),綁定0號端口,系統(tǒng)會隨機(jī)分配一個可用的端口
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.創(chuàng)建套接字,獲得用戶數(shù)據(jù)
sockfd = init_socket(ip,port);
//2.接收登錄數(shù)據(jù)
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;
//創(chuàng)建子線程,子線程準(zhǔn)備接收當(dāng)前用戶數(shù)據(jù),主線程接續(xù)接收新用戶的秘鑰
pthread_create(&tid,NULL,message_thread,(void *)&packet);
}else{
//秘鑰不正確,使用原始端口回復(fù)信息
sendto(sockfd,&login_flag,sizeof(login_flag),0,(struct sockaddr *)&client_addr,len);
}
//把線程設(shè)置為分離式
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.接收用戶的秘鑰,準(zhǔn)備登錄
user_login(argv[1],argv[2]);
return 0;
}
client
#include
#include
#include
#include
#include /* See NOTES */
#include
#include
#include
#define LOGIN_SUCCESS 1
#define LOGIN_FAILURE 0
void user_login(int sockfd,struct sockaddr_in *addr,struct sockaddr_in *new_addr,int len)
{
int n = 0;
char buf[1024] = {0};
unsigned char flag = LOGIN_FAILURE;
//發(fā)送數(shù)據(jù)
while(1)
{
putchar('>');
memset(buf,0,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf) - 1] = '\0'; //'\n'-->'\0'
n = sendto(sockfd,buf,strlen(buf),0,(struct sockaddr *)addr,len);
if(n < 0)
{
perror("Fail to sendto");
exit(EXIT_FAILURE);
}
recvfrom(sockfd,&flag,sizeof(flag),0,(struct sockaddr *)new_addr,&len);
//說明登錄成功,否則繼續(xù)登錄
if(flag == LOGIN_SUCCESS)
break;
}
return ;
}
void send_message(int sockfd,struct sockaddr_in *addr,int addr_len)
{
int n = 0;
char buf[1024] = {0};
//發(fā)送數(shù)據(jù)
while(1)
{
printf("Input : ");
memset(buf,0,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf) - 1] = '\0'; //'\n'-->'\0'
n = sendto(sockfd,buf,strlen(buf),0,(struct sockaddr *)addr,addr_len);
if(n < 0)
{
perror("Fail to sendto");
exit(EXIT_FAILURE);
}
if(strncmp(buf,"quit",4) == 0)
break;
}
return ;
}
//./a.out ip port
int main(int argc, const char *argv[])
{
int sockfd = 0;
struct sockaddr_in peer_addr;
struct sockaddr_in server_addr;
socklen_t len = sizeof(peer_addr);
if(argc < 3)
{
fprintf(stderr,"Usage : %s ip port!\n",argv[0]);
exit(EXIT_FAILURE);
}
//1.通過socket創(chuàng)建文件描述符
sockfd = socket(AF_INET,SOCK_DGRAM ,0);
if(sockfd < 0)
{
perror("Fail to socket!");
exit(EXIT_FAILURE);
}
//2.填充服務(wù)器的ip地址和port,方便綁定
memset(&peer_addr,0,sizeof(peer_addr));
peer_addr.sin_family = AF_INET;
peer_addr.sin_port = htons(atoi(argv[2]));
peer_addr.sin_addr.s_addr = inet_addr(argv[1]);
//3.發(fā)送登錄數(shù)據(jù)
memset(&server_addr,0,sizeof(server_addr));
user_login(sockfd,&peer_addr,&server_addr,len);
//4.發(fā)送交互數(shù)據(jù)
send_message(sockfd,&server_addr,len);
//5.關(guān)閉文件描述符
close(sockfd);
return 0;
}
【圖片】
【圖片】