TCP项目 云词典

本文讲述了如何使用socket库在客户端和服务器间实现TCP通信,涉及账号管理、数据库操作、多线程处理、用户界面设计以及错误处理等内容。服务器使用io多路复用处理并发请求,数据库用于存储用户信息和词典数据。
摘要由CSDN通过智能技术生成

难点:

使用socket库创建和管理套接字,实现客户端和服务器的网络通信。
客户端使用TCP协议与服务器建立连接,并发送请求和接收响应。
客服端使用多线程或者多进程分别处理键盘输入或者服务器的响应。
服务器使用io多路复用来处理多个客户端的并发请求。
使用数据库存储用户的账号密码,并设定key值。
使用数据库存储词典数据,服务器根据客户端请求查询对应的数据。
使用适当的数据结构来组织和存储词典数据,以便快速查询。
使用链表等数据结构管理每个用户的查找记录,以便用户查看。
实现用户友好的界面,并提供错误处理和异常情况。

  1. 客户端功能:

    • 与服务器建立TCP连接。
    • 账号注册及出错反馈。
    • 用户登录成功或失败反馈
    • 登录成功将提供用户界面,接收用户输入的单词。
    • 将用户输入的请求发送给服务器。
    • 接收并显示服务器返回的结果,包括词义、解释等。
    • 提供查询历史记录等。
  2. 服务器功能:

    • 采用io多路复用,监听指定的端口,等待一个或多个客户端连接。
    • 接收客户端发送的请求。
    • 使用数据库,建立单词表和用户信息表
    • 根据请求查询相应的词义和解释。
    • 将查询结果发送给客户端。
    • 根据客户端输入的请求,反馈结果给客户。

源码 

服务器

void Register(int acceptfd, sqlite3 *db);
void Login(int acceptfd, sqlite3 *db);
void Query(int acceptfd, sqlite3 *db);
void History(int acceptfd,sqlite3 *db);

int main(int argc, char const *argv[])
{ 
	//输入容错
	if (argc != 2)
	{
		printf("Usage : %s <port>\n", argv[0]);
		return -1;
	}
	//创建sockfd套接字
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd < 0)
	{
		perror("socket is err:");
		return -1;
	}
	struct sockaddr_in saddr, caddr;
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(atoi(argv[1]));
	saddr.sin_addr.s_addr = inet_addr("0.0.0.0");
	int addrlen = sizeof(caddr);
	//绑定套接字
	if (bind(sockfd, (struct sockaddr *)&saddr, addrlen))
	{
		perror("bind err:");
		return -1;
	}
	//启动监听
	if (listen(sockfd, 5))
	{
		perror("listen err:");
		return -1;
	}
	//打开数据库
	sqlite3 *db = NULL;						   //防止野指针
	char *errmsg = NULL;					   //一个库
	if (sqlite3_open("./cidian.db", &db) != 0) //两个表 帐号密码表 历史记录表
	{
		fprintf(stderr, "sqlite3_err %s\n", sqlite3_errmsg(db));
		return -1;
	}
	printf("open cidian sucess\n");


	if (sqlite3_exec(db, "create table usr(name char primary key ,password char);", NULL, NULL, &errmsg) != SQLITE_OK)
	{
		fprintf(stderr, "sqlite3_exec:%s\n", errmsg);
	}
	if (sqlite3_exec(db, "create table history(name char,word char,time char);", NULL, NULL, &errmsg) != SQLITE_OK)
	{
		fprintf(stderr, "sqlite3_exec:%s\n", errmsg);
	}
	while (1)
	{
		//连接
		int acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &addrlen);
		if (acceptfd < 0)
		{
			perror("accept err");
			return -1;
		}
		printf("client IP is: %s,PORT is: %d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
		//多进程
		pid_t pid = fork();
		if (pid < 0)
		{
			perror("fork err");
			return -1;
		}
		else if (pid == 0)
		{
			close(sockfd);
			
			while (1)
			{
				//循环接收
				int ret = recv(acceptfd, &msg, sizeof(msg), 0);
				if (ret < 0)
				{
					perror("recv is err");
					return -1;
				}
				else if (ret == 0)
				{
					break;
				}
				else
				{
					switch (msg.type)
					{
					case 'R':
						Register(acceptfd, db);
						break;
					case 'L':
						Login(acceptfd, db);
						break;
					case 'Q':
						Query(acceptfd,db);
						break;
					case 'H':
						History(acceptfd, db);
						break;
					}
				}
			}
			printf("client exit\n");
			close(acceptfd);
			exit(0);
		}
		else
		{
			close(acceptfd);
		}
	}
	close(sockfd);
	sqlite3_close(db);
	return 0;
}

客户端

#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>

typedef struct
{
    int type;
    char name[128];
    char text[256];
} MSG;
struct sockaddr_in saddr;
MSG msg;
int n;
//char word[64];

void list1();
void list2();
void do_register(int sockfd);
void do_login(int sockfd);
void query_word(int sockfd);
void history_record(int sockfd);

int main(int argc, char const *argv[])
{
    if (argc != 3)
    {
        printf("Useage:%s <ip> <port>\n", argv[0]);
        return -1;
    }
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);

    if (sockfd < 0)
    {
        perror("sockfd is err");
        return -1;
    }
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[2]));
    saddr.sin_addr.s_addr = inet_addr(argv[1]);

    if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("connect is err");
        return -1;
    }

    while (1)
    {
        list1();
        printf("please choose  number :");
        scanf("%d", &n);
        getchar();
        switch (n)
        {
        case 1:
            do_register(sockfd);
            break;
        case 2:
            do_login(sockfd);
            break;
        case 3:
            close(sockfd);
            exit(0);

        default:
            printf("输入格式有误,请重输\n");
            break;
        }
        if (msg.type == 1)
            goto loop;
    }
loop:
    while (1)
    {
        list2();
        printf("please choose num:");
        scanf("%d", &n);
        getchar();
        switch (n)
        {
        case 1:
            query_word(sockfd);
            break;
        case 2:
            history_record(sockfd);
            break;
        case 3:
            close(sockfd);
            printf("nice to meetyou!! bye\n");
            exit(0);
        default:
            printf("输入格式有误,请重新输入\n");
            break;
        }
    }

    return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值