コード例 #1
0
ファイル: client.c プロジェクト: csdaiwei/netlab03
/*a thread created after login, to receive all packets from server
 *the main thread will no more receive packet after this thread created*/
void *
recv_packet_thread(void *this_is_no_use){

	int n = 0;	//number received 
	while( (n = readvrec(client_sock, recvbuf, BUF_SIZE)) > 0){
		struct im_pkt_head *response_head = (struct im_pkt_head *)recvbuf;
		char *response_data = (char *)(response_head + 1);
		//struct im_pkt_head *response_head = (struct im_pkt_head *)sendbuf;
		//int response_data_size;
		//printf("debug:received a packet from socket:%d, type:%d, service:%d, data size:%d\n"
		//	, client_socket, request_head -> type, request_head -> service, request_head -> data_size);

		memset(sendbuf, 0, sizeof(sendbuf));
		if(response_head -> type != TYPE_RESPONSE){
			printf("\nReceived a error packet, drop it.\n enter >> ");
			break;
		}
		switch(response_head -> service){
			/*case SERVICE_LOGIN: ;
				break;
			case SERVICE_LOGOUT: ;
				break;
			case SERVICE_QUERY_ONLINE: ;
				break;*/
			case SERVICE_SINGLE_MESSAGE: ;
				char *sender = response_data;
				char *text = response_data + 40;/*two names' length*/
				printf("\nMessage comes from %s:\n \t%s\nenter >> ", sender,text);
				fflush(stdout);
				save_recent_messages(sender, text);
				break;
			case SERVICE_MULTI_MESSAGE: ;
				sender = response_data;
				text = response_data + 20;/*one name's length*/
				printf("\nMessage comes from %s:\n \t%s\nenter >> ", sender,text);
				fflush(stdout);
				save_recent_messages(sender, text);
				break;
			case SERVICE_ONLINE_NOTIFY: ;
				char *that_online_username = response_data;
				if(find_user_by_name(online_friend_queue, that_online_username) == NULL){
					struct user_node *n = init_user_node(-1, that_online_username);
					enqueue(online_friend_queue, n);
				}
				break;
			case SERVICE_OFFLINE_NOTIFY: ;
				char *that_offline_username = response_data;
				delete_user_by_name(online_friend_queue, that_offline_username);
				break;
			default:
				printf("\nReceived a error packet, drop it.\n enter >> ");break;
		}
		memset(recvbuf, 0, sizeof(recvbuf));
	}
	if( n < 0)
		printf("Read error\n");
	pthread_exit(NULL);
}
コード例 #2
0
ファイル: client.c プロジェクト: csdaiwei/netlab03
/*send a login request to server*/
void 
login(){

	if(system("clear"));//unused warnning

	printf(	"Hello, this is an IM program.\n" 
			"You may pick a nickname and login.\n"
			"==========================================\n");
	while(true){
		while(true){
			printf("Your name (no more than 15 characters):");
			if(get_keyboard_input(username, 20) >= 3)
				break;
			else
				printf("It's too short.\n");
		}
		/*construct a login request packet and send it*/
		memset(sendbuf, 0, sizeof(sendbuf));
		unsigned short data_size = 20;	//request im packet data size
		construct_im_pkt_head((struct im_pkt_head *)sendbuf, TYPE_REQUEST, SERVICE_LOGIN, data_size);
		concat_im_pkt_data((struct im_pkt_head *)sendbuf, username);
		send(client_sock, sendbuf, IM_PKT_HEAD_SIZE + data_size, 0);

		/*get and parse the response packet*/
		memset(recvbuf, 0 ,sizeof(recvbuf));
		int n = readvrec(client_sock, recvbuf, BUF_SIZE);
		struct im_pkt_head *response_head = (struct im_pkt_head *)recvbuf;
		if( (n == 1) && (response_head -> service == SERVICE_LOGIN)){	//the response data size is 1
			char *response_data = (char *)(response_head + 1);//right after the head
			bool login_success = (bool) response_data[0];
			if(login_success){
				query_online_all();
				break;
			}
			else{	//login falied. name repeat
				printf(	"\nSorry, that name seems to have been taken, pick another one!\n");
				continue;
			}
		}
		printf("Sorry ,the server seems overloaded, wait a moment and try again.\n");
		exit(-1);
	}
}
コード例 #3
0
int main(int argc,char **argv)
{
	struct sockaddr_in peer;
	SOCKET s;
	SOCKET s1;
	int peerlen = sizeof(peer);
	int n;
	char buf[10];

	INIT();

	if(argc == 2)
	{
		s = tcp_server(NULL,argv[1]);
	}
	else
	{
		s = tcp_server(argv[1],argv[2]);
	}
	s1 = accept(s,(struct sockaddr*)&peer,(socklen_t *)&peerlen);
	if(!isvalidsock(s1))
	{
		error(1,errno,"accept failed");
	}

	for(;;)
	{
		n = readvrec(s1,buf,sizeof(buf));
		if(n < 0)
		{
			error(0,errno,"readvrec returned error");
		}
		else if(n == 0)
		{
			error(1,0,"client disconnected\n");
		}
		else
		{
			write(1,buf,n);
		}
	}
	EXIT(0);
}
コード例 #4
0
ファイル: client.c プロジェクト: csdaiwei/netlab03
/*query for all online friends' names*/
void
query_online_all(){
	/*build a query packet*/
	memset(sendbuf, 0, sizeof(sendbuf));
	int data_size = 0;
	construct_im_pkt_head((struct im_pkt_head *)sendbuf, TYPE_REQUEST, SERVICE_QUERY_ONLINE, data_size);
	//concat_im_pkt_data((struct im_pkt_head *)sendbuf, NULL);
	send(client_sock, sendbuf, IM_PKT_HEAD_SIZE + data_size, 0);

	/*get and parse the response packet*/
	memset(recvbuf, 0 ,sizeof(recvbuf));
	readvrec(client_sock, recvbuf, BUF_SIZE);
	struct im_pkt_head *response_head = (struct im_pkt_head *)recvbuf;
	assert((response_head -> type == TYPE_RESPONSE) && 
		(response_head -> service == SERVICE_QUERY_ONLINE));

	/*add all user into online_friend_queue*/
	int i;
	for (i = 0; i < response_head -> data_size / 20; ++i){
		struct user_node *pnode = init_user_node(-1, (char *)(response_head + 1) + 20 * i);
		enqueue(online_friend_queue, pnode);
	}
	
}
コード例 #5
0
ファイル: server.c プロジェクト: csdaiwei/netlab03
void 
*client_handler(void * connfd){

	int n;	/*number received*/
	char username[20];	//the user's name connecting to this thread. will be filled when login
	int status = -1;	//the user's status
	int client_socket = (int)connfd;	//the user's socket connecting to this thread;
	//debug://long tid = pthread_self();

	assert(online_user_queue != NULL);
		
	/*each thread has its own buf*/
	char sendbuf[BUF_SIZE];
	char recvbuf[BUF_SIZE];
	
	//printf("debug:thread %lu created for dealing with client requests\n", tid);

	/*Receive the request im packet by two steps.
	 *Firstly receive the head field, secondly receive the data field.
	 *Then handle the request packet (usually by a response packet)*/
	while( (n = readvrec(client_socket, recvbuf, BUF_SIZE)) > 0){
		struct im_pkt_head *request_head = (struct im_pkt_head *)recvbuf;
		struct im_pkt_head *response_head = (struct im_pkt_head *)sendbuf;
		char *request_data = (char *)(request_head + 1);
		int response_data_size = 0;
		//printf("debug:received a packet from socket:%d, type:%d, service:%d, data size:%d\n"
		//	, client_socket, request_head -> type, request_head -> service, request_head -> data_size);

		memset(sendbuf, 0, sizeof(sendbuf));
		if(request_head -> type != TYPE_REQUEST){
			printf("Received a error packet, drop it.\n");
			break;
		}
		
		switch(request_head -> service){
			case SERVICE_LOGIN: ;
				/*response a login response packet, 
				 *it contains only 1 byte data to indicate that login succeeded or failed*/
				response_data_size = 1;
				bool login_result;
				strncpy(username, (char *)(request_head + 1), 20);
				
				//check repeat
				pthread_mutex_lock(&mutex);
				if(find_user_by_name( online_user_queue, username) == NULL){
					//printf("debug:here2\n");
					struct user_node *pnode = init_user_node(client_socket, username);
					enqueue(online_user_queue, pnode);
					status = ONLINE_STATUS;
					printf("\tuser %s login.\n", username);
					login_result = true;
					/*notify all othre users*/
					on_off_line_notify(SERVICE_ONLINE_NOTIFY, username, sendbuf);
				}
				else{
					login_result = false;
				}
				pthread_mutex_unlock(&mutex);
				//printf("debug: thread %lu release lock\n", tid);
				construct_im_pkt_head(response_head, TYPE_RESPONSE, SERVICE_LOGIN, response_data_size);
				concat_im_pkt_data(response_head, (char *)&login_result);
				send(client_socket, sendbuf, IM_PKT_HEAD_SIZE + response_data_size, 0);
				//printf("debug:response packet send to socket:%d, type:%d, service:%d, data size:%d\n"
				//	, client_socket, response_head -> type, response_head -> service, response_head -> data_size);
				break;
			case SERVICE_LOGOUT: ;
				/*nothing need to do here.*/
				break;
			case SERVICE_QUERY_ONLINE: ;

				/*copy all usernames into the data field of the response packet*/
				pthread_mutex_lock(&mutex);
				response_data_size = 20 * copy_all_user_name((char *)(response_head + 1), online_user_queue);
				pthread_mutex_unlock(&mutex);
				construct_im_pkt_head(response_head, TYPE_RESPONSE, SERVICE_QUERY_ONLINE, response_data_size);
				/*send the packet*/
				send(client_socket, sendbuf, IM_PKT_HEAD_SIZE + response_data_size, 0);
				break;
			case SERVICE_SINGLE_MESSAGE: ;
				//printf("debug: sender %s, recipient %s, text %s\n", request_data, request_data + 20, request_data + 40);
				/*simple resend the packet to the recipient*/
				char *recipient = request_data + 20;
				struct user_node *recipient_node = find_user_by_name(online_user_queue, recipient); 
				if(recipient_node != NULL){
					response_data_size = request_head -> data_size;
					construct_im_pkt_head(response_head, TYPE_RESPONSE, SERVICE_SINGLE_MESSAGE, response_data_size);
					concat_im_pkt_data(response_head, request_data);
					send(recipient_node -> socket, sendbuf,IM_PKT_HEAD_SIZE + response_data_size, 0);
				}else
					printf("Error, no recipient %s. drop the packet\n", recipient);
				break;
			case SERVICE_MULTI_MESSAGE: ;
				//printf("debug: sender %s, recipient all, text %s\n", request_data, request_data + 20);
				response_data_size = request_head -> data_size;
				construct_im_pkt_head(response_head, TYPE_RESPONSE, SERVICE_MULTI_MESSAGE, response_data_size);
				concat_im_pkt_data(response_head, request_data);
				char *sender = request_data;
				/*send to all online users except this message's sender*/
				for(recipient_node = online_user_queue -> front; recipient_node != NULL; recipient_node = recipient_node -> next)
					if(strcmp(recipient_node -> username, sender) != 0)
						send(recipient_node -> socket, sendbuf,IM_PKT_HEAD_SIZE + response_data_size, 0);
				break;
			default:
				printf("Received a error packet, drop it.\n");break;
		}
		memset(recvbuf, 0, sizeof(recvbuf));
	}
	if( n < 0)
		printf("Read error\n");

	if(status == ONLINE_STATUS){
		/*remove logout or disconnected  users from the queue*/
		on_off_line_notify(SERVICE_OFFLINE_NOTIFY, username, sendbuf);
		pthread_mutex_lock(&mutex);
		delete_user_by_name(online_user_queue, username);
		pthread_mutex_unlock(&mutex);
		status = -1;
		printf("\tuser %s logout\n", username);
	}
	pthread_exit(NULL);
}