本地怎样上传自己做的网站,网站打不开怎么解决,外贸公司查询,织梦备份网站数据socket是实现进程通信的一种重要方式#xff0c;本文将通过socket编程实现服务器进程与客户端进程之间的通信#xff0c;并在通信之外实现猜数字的小游戏。
1. 设计思路
本文设计的C/S结构的猜数字游戏功能如下#xff1a;服务器端自动生成一个1-100之间的随机数字#x…socket是实现进程通信的一种重要方式本文将通过socket编程实现服务器进程与客户端进程之间的通信并在通信之外实现猜数字的小游戏。
1. 设计思路
本文设计的C/S结构的猜数字游戏功能如下服务器端自动生成一个1-100之间的随机数字用户在客户端根据提示输入所猜的数字若用户猜的数字和服务器所生成的数字相同则游戏通关用户可选择是否进入下一轮。当用户输入负数时退出游戏。
设计要点如下 服务端通信部分 为实现客户端与服务器进程的相互通信在服务端首先创建一个socket设置socket属性并调用函数bind()绑定IP地址、端口等信息然后调用函数listen()开启监听调用函数accept()阻塞等待客户端的连接请求接下来调用函数recv()和send()收发数据最后关闭网络连接和监听。 客户端通信部分 在客户端也是先调用函数socket()创建一个socket设置socket属性然后调用函数connect()连接服务器调用函数recv()和send()收发数据最后关闭网络连接。服务端与客户端的通信过程如下图所示。 服务端处理方式 服务端采用多线程的方式处理客户端的请求。主线程每收到一个来自客户端的TCP连接请求就调用pthread_create()函数创建一个子线程与之对应连接。一个线程处理一个客户端从而实现了一个服务器与多个客户端之间的通信。 猜数字功能设计 server生成一个1到100之间的随机数client去猜。client把每次猜的数字发给server。server收到后会把猜的数字偏大、偏小、或是猜对的提示发给client。如果client不想继续猜了发给server一个负数则退出游戏。否则一直到client猜对数字用户选择不再进行下一轮游戏结束。
2. 程序代码
2.1 服务器端server.c
服务器端代码server.c的具体实现如下
#include stdio.h
#include stdlib.h
#include errno.h
#include string.h
#include sys/types.h
#include netinet/in.h
#include sys/socket.h
#include sys/wait.h
#include arpa/inet.h
#include pthread.h
#include time.h#define PORT 1500//端口号
#define BACKLOG 5/*最大监听数*/
#define MAX_DATA 1024//接收到的数据最大长度 /**判断client猜的数字answer和server想的数字num是否相等*若相等返回1;不相等则返回0*/
int isEqual(int c, int answer, int num) {if (answer num) {send(c, Too small! Please guess again:, MAX_DATA, 0);printf(Thinking: %d is too small!\n, answer);return 0;} else if (answer num) {send(c, Too big! Please guess again:, MAX_DATA, 0);printf(Thinking: %d is too big!\n, answer);return 0;}else if (answer num) {send(c, Bingo!, MAX_DATA, 0);printf(Thinking: Bingo, %d is the right answer!\n, answer);return 1;}
}void guess_num(int *arg) {int c *arg;char myrecv[MAX_DATA]; //储存收到的信息char mysend[MAX_DATA]; //储存发出的信息srand((int)time(NULL));int num rand() % 100 1; //server想的数字为[1,100)的随机数send(c, Im thinking a number between 1 and 100! Guess what I think?, MAX_DATA, 0);int bingo 0; //bingo标志是否猜对若猜对bingo0;否则bingo1while (bingo 0) {memset(myrecv, \0, sizeof(myrecv));memset(mysend, \0, sizeof(mysend));recv(c, myrecv, MAX_DATA, 0);printf(The client guesses %s\n, myrecv);int answer atoi(myrecv);if (answer 0) { //若client输入了一个负数则退出游戏send(c, Exit game..., MAX_DATA, 0);printf(Sent: Exit game...\n);break;}bingo isEqual(c, answer, num);}pthread_exit(NULL);
}int main() { int sockfd, new_fd;/*socket句柄和建立连接后的句柄*/ struct sockaddr_in my_addr;/*本方地址信息结构体下面有具体的属性赋值*/ struct sockaddr_in their_addr;/*对方地址信息*/ int sin_size; sockfd socket(AF_INET,SOCK_STREAM,0);//建立socket if (sockfd -1) { printf(socket failed:%d, errno); return -1; } my_addr.sin_family AF_INET;/*该属性表示接收本机或其他机器传输*/ my_addr.sin_port htons(PORT);/*端口号*/ my_addr.sin_addr.s_addr htonl(INADDR_ANY);/*IP括号内容表示本机IP*/ bzero((my_addr.sin_zero), 8);/*将其他属性置0*/ if (bind(sockfd, (struct sockaddr*)my_addr, sizeof(struct sockaddr)) 0) {//绑定地址结构体和socket printf(bind error); return -1; } printf(bind OK\n);listen(sockfd, BACKLOG);//开启监听 第二个参数是最大监听数 printf(listening\n); while (1) { sin_size sizeof(struct sockaddr_in); new_fd accept(sockfd, (struct sockaddr*)their_addr, sin_size);//在这里阻塞知道接收到消息参数分别是socket句柄接收到的地址信息以及大小 if (new_fd -1) { continue; } else {printf(accept: c %d, ip %s, port %d\n, new_fd, inet_ntoa(my_addr.sin_addr), ntohs(my_addr.sin_port));send(new_fd, Connect sucess\n, MAX_DATA, 0);//发送内容参数分别是连接句柄内容大小其他信息设为0即可pthread_t id; //新建线程可连接多个客户端pthread_create(id, NULL, (void *)guess_num, new_fd); }} close(sockfd);return 0;
} 2.2 客户端client.c
客户端代码client.c的具体实现如下
#include stdio.h
#include stdlib.h
#include errno.h
#include string.h
#include sys/types.h
#include netinet/in.h
#include sys/socket.h
#include sys/wait.h
#include pthread.h#define DEST_PORT 1500//目标地址端口号
#define DEST_IP 127.0.0.1/*目标地址IP这里设为本机*/
#define MAX_DATA 1024//接收到的数据最大长度 int main() { int sockfd, new_fd;/*cocket句柄和接受到连接后的句柄 */ struct sockaddr_in dest_addr;/*目标地址信息*/ char myrecv[MAX_DATA];//储存接收数据char mysend[MAX_DATA];//储存发送数据 sockfd socket(AF_INET,SOCK_STREAM,0);/*建立socket*/ if (sockfd-1) { printf(socket failed:%d,errno); } //参数意义见上面服务器端 dest_addr.sin_family AF_INET; dest_addr.sin_port htons(DEST_PORT); dest_addr.sin_addr.s_addr inet_addr(DEST_IP); bzero((dest_addr.sin_zero), 8); if (connect(sockfd, (struct sockaddr*)dest_addr, sizeof(struct sockaddr)) -1) {//连接方法传入句柄目标地址和大小 printf(connect failed:%d,errno);//失败时可以打印errno } else { memset(myrecv, \0, sizeof(myrecv));recv(sockfd,myrecv,MAX_DATA,0); //接收Connect sucessprintf(Received: %s\n, myrecv); recv(sockfd,myrecv,MAX_DATA,0); //接收Im thinking a number ...printf(Received: %s\n, myrecv); while (1) {memset(mysend, \0, sizeof(mysend));scanf(%s, mysend);send(sockfd, mysend, MAX_DATA, 0);memset(myrecv, \0, sizeof(myrecv));recv(sockfd, myrecv, MAX_DATA, 0); if(strcmp(myrecv, Bingo!) 0 ||strcmp(myrecv, Exit game...) 0) {printf(%s\n, myrecv);break;}printf(Received: %s\n, myrecv);} } close(sockfd);//关闭socket return 0;
} 3. 运行结果 若可执行文件未生成首先使用gcc server.c -lpthread -o server与gcc client.c -lpthread -o client命令生成可执行文件server与client若可执行文件已存在转步骤2。注意 由于pthread库不是Linux系统默认的库连接时需要使用库libpthread.a,所以在使用pthread_create创建线程时在编译中要加-lpthread参数。 使用./server命令运行服务端程序如下图所示。 使用./client命令运行客户端程序。启动3个客户端均显示已和服务器连接成功如下图所示。 用户根据提示“Too small”/“Too big”在客户端重复输入所猜数字直至猜对屏幕输出“Bingo”。若用户一直未猜对输入任意负数即可退出游戏客户端程序结束。如下图所示。