Linux c线程客户端服务器端初探
2016-12-01 15:17
232 查看
这段时间在上嵌入式实验的课,老师正好讲到Linux网络编程这一块,自己也正好在看这一块,所以作为初学者记录一下鼓励一下自己喽! 这里老师对我们的要求是客户端能连续发送数据不需要等待服务器的应答,客户端也能及时收到服务器端连续发送的数据。对此,就要将发送和接收分开,使用线程的方式。 而对服务器端的程序要求是,当接收到字母N开头的字符串时取出N后面的整数,并判断该整数是不是一个幸运素数(4位以上的素数,并且只有一位数字和其它位不同),将判断结果返回给客户端。如客户端发送N4321, 服务器端应答NO, 发送N9999991, 服务器端应答YES。 接下去给出了client.c和server.c程序,仅供参考。
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/socket.h> #include <netdb.h> #include <netinet/in.h> #include <sys/types.h> #include <pthread.h> #define PORT 4321 #define BUF_SIZE 1024 int sockfd,sendbytes,recvbytes; char buf[BUF_SIZE]; struct hostent* host; struct sockaddr_in serv_addr; pthread_t thread1; /*********************************************************************** #include <netdb.h> #include <sys/socket.h> struct hostent { char *h_name; 地址的正式名称 char **h_aliases; 空字节-地址的预备名称的指针 int h_addrtype; 地址类型; 通常是AF_INET int h_length; 地址的比特长度。 char **h_addr_list; 零字节-主机网络地址指针。网络字节顺序。 }; #define h_addr h_addr_list[0] h_addr_list中的第一地址。 ************************************************************************/ /*********************************************************************** #include <netinet/in.h> struct sockaddr_in{ sa_family_t sin_family; 16位的地址族 in_port_t sin_port; 16位的端口号 struct in_addr sin_addr; 32位的IP地址 unsigned char sin_zero[8]; 填充区,8个字节填充0 } struct in_addr{ in_addr_t s_addr; } ************************************************************************/ //pthread function to recieve content from the buffer void* thfn1(void* arg){ bzero(buf,sizeof(buf)); if((recvbytes = recv(sockfd,buf,BUF_SIZE,0)) == -1){ perror("recv"); exit(1); } else{ printf("receive from %d(socket):%s",sockfd,buf); } return NULL; } int main(int argc,char* argv[]){ //check the argument of the programme if(argc < 2){ printf("USAGE:./tclient Hostname(or ip address)\n"); exit(1); } //check the server address which the argument of the programme imply if((host = gethostbyname(argv[1])) == NULL){ perror("gethostbyname"); exit(1); } //create a socket if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1){ perror("socket"); exit(1); } //init the struct variables of the serv_addr serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); serv_addr.sin_addr = *((struct in_addr*)host->h_addr); bzero(&(serv_addr.sin_zero),8); //connect to the server if(connect(sockfd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr)) == -1){ perror("connect"); exit(1); } //display the information of the connection printf("connect to server %s...\nInput the msg to send:\n",argv[1]); //send and recieve the information from the server circularly while(1){ bzero(buf,sizeof(buf)); //clean the buffer if(fgets(buf,BUF_SIZE,stdin)){ if(strcmp(buf,"exit\n") == 0) //judge if need to break break; if((sendbytes = send(sockfd,buf,strlen(buf),0)) == -1){ perror("send"); exit(1); } } if(pthread_create(&thread1,NULL,thfn1,NULL)){ //create a pthread printf("fail to create a pthread!"); exit(1); } } close(sockfd); return 0; }
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <time.h> #include <string.h> #include <math.h> #include <sys/ioctl.h> #include <arpa/inet.h> #define PORT 4321 #define MAX_QUE_CONN_NM 5 #define MAX_SOCK_FD FD_SETSIZE #define BUFFER_SIZE 1024 #define HOSTLEN 256 //determine whether a prime number int isprime(int k){ int i; for(i=2;i<=sqrt(k);i++){ if(k%i == 0) break; } if(i > sqrt(k)) return 1; else return 0; } //determine whether a lucky number unsigned char checkNN(int n) { //if(n < N/10) // return 0; unsigned char res[10],i,cn=0,tn=0; memset(res,0,10); while(n > 0) { res[n%10] += 1; n /= 10; } for(i=0;i<10;++i) { if(res[i] > 1) ++cn; if(res[i]) ++tn; } if(tn < 3 && cn < 2)//最多只有2种字符,且只有1种字符个数超过1个 return 1; else return 0; } int main() { struct sockaddr_in server_sockaddr, client_sockaddr; int sin_size, count,k; fd_set inset, tmp_inset; int sockfd, client_fd, fd; char buf[BUFFER_SIZE]; // 接收、 发送缓冲 struct sockaddr_in scinf[100]; // 客户端地址池 bzero((void *)scinf, sizeof(scinf)); // 创建socket if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } // 初始化服务器地址结构体 server_sockaddr.sin_family = AF_INET; server_sockaddr.sin_port = htons(PORT); server_sockaddr.sin_addr.s_addr = INADDR_ANY; bzero(&(server_sockaddr.sin_zero), 8); // 为bind设置地址复用 int i = 1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); if (bind(sockfd, (struct sockaddr *)&server_sockaddr, sizeof(struct sockaddr)) == -1) { //绑定套接字和地址 perror("bind"); exit(1); } // 开始侦听客户端连接 if (listen(sockfd, MAX_QUE_CONN_NM) == -1) { perror("listen"); exit(1); } printf("Begin listening...\n"); // 准备非阻塞方式连接多路客户端 FD_ZERO(&inset); //清空位向量所有位 FD_SET(sockfd, &inset); //设置为向量指定位 while (1) { tmp_inset = inset; sin_size = sizeof(struct sockaddr_in); memset(buf, 0, sizeof(buf)); if (!(select(MAX_SOCK_FD, &tmp_inset, NULL, NULL, NULL) > 0)) {//等待网络消息 perror("select"); exit(1); } for (fd = 0; fd < MAX_SOCK_FD; ++fd) { if (FD_ISSET(fd, &tmp_inset) > 0) { if (fd == sockfd) { // 有客户端连接请求, accept之 if ((client_fd = accept(sockfd, (struct sockaddr*)&client_sockaddr, &sin_size)) == -1) { perror("accept"); exit(1); } FD_SET(client_fd, &inset); printf("New connection from %s\n", inet_ntoa(client_sockaddr.sin_addr)); if (client_fd < 100 && client_fd >= 0) // 新连接客户端记入地址池 memcpy((void *)(&scinf[client_fd]), (void *)&client_sockaddr, sin_size); } else { // 有客户端数据 if ((count = recv(fd, buf, BUFFER_SIZE, 0)) > 0) { // 接收数据 if (fd >= 0 && fd < 100){ if(buf[0] == 'N'){ k= atoi(buf+1); if(k >9999 && isprime(k)){ if(checkNN(k)) sprintf(buf,"Yes\n"); } else sprintf(buf,"No\n"); } else sprintf(buf,"No\n"); } //printf("Received from %s:\t%s", inet_ntoa(scinf[fd].sin_addr), buf); if ((count = send(fd, buf, strlen(buf), 0)) == -1) { // 回送数据 perror("send"); exit(1); } } else { // 无法读取数据, 可能连接以断开 if (fd >= 0 && fd < 100) printf("Client %s has left\n", inet_ntoa(scinf[fd].sin_addr)); memset((void *)(&scinf[client_fd]), 0, sin_size); close(fd); FD_CLR(fd, &inset); } } } } //bzero(buf,sizeof(buf)); } close(sockfd); return 0; }
相关文章推荐
- java socket实现的客户端和服务器端,服务器采用多线程实现,为每个客户分配一个线程
- socket用线程实现客户端和服务器端连续发送数据
- LInux中利用线程实现多个客户端和服务器端进行通信
- JavaSE第一百一十讲:使用线程实现服务器端与客户端的双向通信
- 6.服务器与客户端双线程传输文件--服务器端
- udp 多线程客户端和单线程服务器端
- java_web当中客户端-服务器端对于中文编码格式的处理
- 表单的验证:客户端验证和服务器端验证
- 基于Linux c 用socket和线程 实现的简易聊天室之服务器
- 用服务器端控件给客户端控件赋值
- Android客户端与服务器端交互,如何保持session回话
- pytho网络通信服务器端和客户端建立通信
- java聊天程序客户端和服务器端,BUG中。。。。。
- 客户端与服务器端Socket的区别与联系?
- 浅析Java web程序之客户端和服务器端交互原理
- 客户端的跳转与服务器端的跳转的区别
- ASP.NET AJAX 使用客户端调用服务器端的方法
- delphi7编写客户端调用java服务器端webservice示例
- 解决DoubanFM第三方客户端UI线程与工作线程交互问题