TA的每日心情 | 慵懒 前天 10:54 |
---|
签到天数: 186 天 连续签到: 2 天 [LV.7]常住居民III
|
本帖最后由 stm1024 于 2023-12-9 22:03 编辑
0. 前言
前面测试过UDP和TCP的程序,显示功能正常,但是测试程序中都是单点之间的通讯,而且服务端和客户端,要有严格的顺序,并且,客户端或者服务端挂掉以后,另一边也会受到影响。此外,实际使用的时候可能有多个客户端连接服务端,此时我们可以考虑使用多进程或者多线程,但是使用多进程的话,占用的资源比较多,这个对一般的入门级嵌入式linux处理器不太友好,此外,还有可能会带来IPC(进程间通讯)的工作,因此,常见的嵌入式环境下,使用的是单进程+多线程,而不是多线程+单进程。
1. 编程规划
前面已经编写过了TCP的服务器端程序和客户端程序。本次重新改写TCP服务器端程序,测试多个客户端的连接。
2. 程序代码
完整的服务端测试代码如下:
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <ctype.h>
- #include <signal.h>
- #include <pthread.h>
- #define SERVER_PORT 12345
- #define BUF_LEN 1024
- #define THREAD_NUM 10
- void dispErrInfo(const char* pretext,int errcode)
- {
- printf("%s, errno=%d: %s\n",pretext,errcode,strerror(errcode));
- }
- void *child(void *arg)
- {
- int i, rcvlen,ret,socketfd;
- i=0;
- rcvlen=-1;
- ret=-1;
- socketfd=*(int*)arg;
- char buf[BUF_LEN];
- memset(buf,0x00,256);
- pthread_t tid=pthread_self();
- printf("[THREAD %lu] ENTER.\n",tid);
- if((rcvlen=recv(socketfd,buf,BUF_LEN,0))==-1)
- {
- close(socketfd);
- dispErrInfo("[THREAD %lu] ERROR.\n",errno);
- exit(EXIT_FAILURE);
- }
- printf("[THREAD %lu] Received From Client:%s.\n",tid,buf);
- //process
- for(i=0;i<rcvlen;i++)
- buf[i]=toupper(buf[i]);
- //send back
- if(send(socketfd,buf,rcvlen,0)==-1)
- {
- close(socketfd);
- dispErrInfo("[THREAD %lu] ERROR.\n",errno);
- exit(EXIT_FAILURE);
- }
- printf("[THREAD %lu] EXIT.\n",tid);
- close(socketfd);
- pthread_exit(NULL);
- }
- int main(int argc, char** argv)
- {
- int socket_desc;
- int temp_socket_desc[THREAD_NUM];
- int t_num=0;
- int address_size;
-
- struct sockaddr_in sin;
- bzero(&sin,sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = INADDR_ANY;
- sin.sin_port = htons(SERVER_PORT);
-
- signal(SIGPIPE, SIG_IGN);
-
- if((socket_desc = socket(AF_INET,SOCK_STREAM,0)) == -1)
- {
- dispErrInfo("Error open socket.\n",errno);
- exit(EXIT_FAILURE);
- }
-
- if(bind(socket_desc,(struct sockaddr *)&sin,sizeof(sin)) ==-1)
- {
- dispErrInfo("Error bind socket.\n",errno);
- exit(EXIT_FAILURE);
- }
- if(listen(socket_desc,20) == -1)
- {
- dispErrInfo("Error listen socket.\n",errno);
- exit(EXIT_FAILURE);
- }
- printf("Waiting connect...\n");
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- while(1)
- {
- pthread_t tid;
- temp_socket_desc[t_num] = accept(socket_desc,NULL, NULL);
- if(temp_socket_desc[t_num] == -1)
- {
- dispErrInfo("Error accept socket.\n",errno);
- break;
- }
- printf("create thread.\n");
- if (pthread_create(&tid,&attr,child,&temp_socket_desc[t_num]) == -1)
- {
- dispErrInfo("Error create thread.\n",errno);
- break;
- }
- t_num = t_num+1;
- if(t_num >= THREAD_NUM)
- {
- break;
- }
- }
- pthread_attr_destroy(&attr);
- return (EXIT_SUCCESS);
- }
复制代码
3. 测试效果
编译,注意我们使用了多线程技术,因此在虚拟机中编译的时候,需要加入 -lpthread,如下:
上图中,agcc是我对/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/agcc做的link。
然后就是常规的拷贝到开发板中,赋予可执行权限等操作,最后运行。
在Windows主机上打开三个网络调试助手,以TCP客户端形式工作,连接服务端:
可见开发板上的程序可以正常收到各服务端发送的数据:
OK,今天测试就到这里。
|
|