/* common.h */ /*服务器端口信息*/ #define PORTLINK ".charport" /*缓存限制*/ #define MAXNAMELEN 256 #define MAXPKTLENE 2048 /*信息类型钉钉*/ #define LIST_GROUPS 0 #define JOIN_GROUP 1 #define LEAVE_GROUP 2 #define USER_TXET 3 #define JOIN_REJECTED 4 #define JOIN_ACCEPTED 5 /*数据包结构*/ typedef struct _packet { /* 数据包类型 数据报类型长度 数据报内容 */ char type; long lent; char *text; }Packet; extern int startserver(); extern int locateserver(); extern Packet *recvpkt(int sd); extern int sendpkt(int sd, char typ, long len, char *buf); extern void freepkt(Packet *msg);
/* ChatLinker.c */ #include<stdio.h> #include<stdlib.h> #include<fcntl.h> #include<string.h> #include<strings.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #include<netdb.h> #include<time.h> #include<errno.h> #include"common.h" /* 为服务器接收客户端请求做准备, 正确返回 socket 文件描述符 错误返回 -1 */ int startserver() { int sd; /* socket 描述符 */ int myport; /* 服务器端口 */ const char *myname; /* 本地主机的全称 */ char linktrgt[MAXNAMELEN]; char linkname[MAXNAMELEN]; /* 调用 socket 函数创建 TCP socket 描述符 */ sd = socket(PF_INET, SOCK_STREAM, 0); /* 调用bind函数将一个本地地址指派给 socket */ struct sockaddr_in server_address; server_address.sin_family = AF_INET; /* 通配地址 INADDR_ANY 表示IP地址为 0.0.0.0, 内核在套接字被连接后选择一个本地地址 htonl函数 用于将 INADDR_ANY 转换为网络字节序 */ server_address.sin_addr.s_addr = htonl(INADDR_ANY); /* 指派为通配端口 0,调用 bind 函数后内核将任意选择一个临时端口 */ server_address.sin_port = htons(0); bind(sd, (struct sockaddr *)&server_address, sizeof(server_address)); /* 调用listen 将服务器端 socket 描述符 sd 设置为被动地监听状态 并设置接受队列的长度为20 */ listen(sd,20); /* 调用 getsockname、gethostname 和 gethostbyname 确定本地主机名和服务器端口号 */ char hostname[MAXNAMELEN]; if (gethostname(hostname, sizeof(hostname)) != 0) { perror("gethostname"); } struct hostent *h; h = gethostbyname(hostname); int len = sizeof(struct sockaddr); getsockname(sd, (struct sockaddr *)&server_address, &len); myname = h->h_name; myport = ntohs(server_address.sin_port); /* 在家目录下创建符号链接'.chatport'指向linktrgt */ sprintf(linktrgt, "%s:%d", myname, myport); /* 在头文件 common.h 中:#define PORTLINK ".chatport" */ sprintf(linkname ,"%s/%s", getenv("HOME"), PORTLINK); if (symlink(linktrgt,linkname) != 0) { fprintf(stderr, "error : server already exists "); return -1; } /* 准备接受客户端请求 */ printf("admin: started server on '%s' at '%d' ", myname, myport); return sd; } /* 和服务器建立连接,正确返回 socket 描述符, 失败返回 -1 */ int hooktoserver() { int sd; char linkname[MAXNAMELEN]; char linktrgt[MAXNAMELEN]; char *servhost; char *servport; int bytecnt; /* 获取服务器地址 */ sprintf(linkname, "%s/%s", getenv("HOME"), PORTLINK); bytecnt = readlink(linkname, linktrgt, MAXNAMELEN); if (bytecnt == -1) { fprintf(stderr,"error : no active char server "); return -1; } linktrgt[bytecnt] = '