socket线程应用
来源:互联网 发布:天竺棉和水洗棉 知乎 编辑:程序博客网 时间:2024/05/21 14:05
声明:本博文用于学习总结及工作心得
server端:
#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/socket.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <netinet/in.h>#include <arpa/inet.h>#include <pthread.h>//改写inet_ntoavoid sockaddr_toa(struct sockaddr_in *addr, char *IPAddr){unsigned char *p = (unsigned char *)&(addr->sin_addr.s_addr);sprintf(IPAddr, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);}pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;int status = 0;struct ps{int socket;pthread_t *t;};//接收客户端的socket数据的线程void *recvsocket(void *arg){struct ps *p = (struct ps *)arg;int st = p->socket;pthread_t t = *(p->t);char s[1024];char *ip = malloc(sizeof(char) *64);//得到远端sockaddrmemset(ip, 0, sizeof(ip));struct sockaddr_in client_addr;socklen_t client_len = sizeof(client_addr);memset(&client_addr, 0, client_len);getpeername(st, (struct sockaddr *)&client_addr, &client_len);sockaddr_toa(&client_addr, ip);printf("远端sockaddr:%s\n", ip);//得到自身的sockaddrmemset(ip, 0, sizeof(ip));struct sockaddr_in server_addr;socklen_t server_len = sizeof(server_addr);memset(&server_addr, 0, server_len);getsockname(st, (struct sockaddr *)&server_addr, &server_len);sockaddr_toa(&server_addr, ip);printf("自身sockaddr:%s\n", ip);while(1){memset(s, 0, sizeof(s));int rc = recv(st, s, sizeof(s), 0);if(rc <= 0)//如果recv小于等于0 代表socket已经关闭或者出错了{break;}else{printf("client:%s\n", s);}}pthread_mutex_lock(&mutex);status--;pthread_mutex_unlock(&mutex);pthread_cancel(t);//被cancel的线程内部没有使用锁return NULL;}void *sendsocket(void *arg)//向client端socket发送数据{int st = *((int *)arg);char s[1024];while(1){memset(s, 0, sizeof(s));read(STDIN_FILENO, s, sizeof(s));//读取用户输入信息send(st, s, strlen(s), 0);}return NULL;}//第二套int main(int arg, char *args[]){ if (arg < 2) { return -1; } int port = atoi(args[1]);int st = socket(AF_INET, SOCK_STREAM, 0);int on =1;//设置socket属性,第三个参数SO_REUSEADDR代表地址可重用if(setsockopt(st, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1){printf("setsockopt failed %s\n", strerror(errno));return EXIT_FAILURE;}struct sockaddr_in addr;memset(&addr, 0, sizeof(addr));addr.sin_family = AF_INET;//设置结构地址类型为TCP/IP地址addr.sin_port = htons(port);//指定一个端口号 8900 htons: 将short类型从host字节类型到net字节类型的转化addr.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY代表这个server上所有的地址//将IP与server程序绑定if(bind(st, (struct sockaddr *)&addr, sizeof(addr)) == -1){printf("bind failed %s\n", strerror(errno));return EXIT_FAILURE;}//server开始listenif(listen(st, 20) == -1){printf("listen failed %s\n", strerror(errno));return EXIT_FAILURE;}int client_st = 0; //client端socketstruct sockaddr_in client_addr;//表示client段的IP地址pthread_t thrd1, thrd2;struct ps p1, p2;while(1){memset(&client_addr, 0, sizeof(client_addr));socklen_t len = sizeof(client_addr);//accept会阻塞,直到有客户端连接过来,accept返回client的socket描述符//client_st = accept(st, p, &len);client_st = accept(st, (struct sockaddr *)&client_addr, &len);pthread_mutex_lock(&mutex);//为全局变量加一个互斥锁,放在与线程函数同时读写变量的冲突status ++;pthread_mutex_unlock(&mutex);//解锁if(status > 1)//当client端连接数大于1时,断开以后的连接{close(client_st);continue;}if(client_st == -1){printf("accept failed %s\n", strerror(errno));return EXIT_FAILURE;} printf("accept by %s\n", inet_ntoa(client_addr.sin_addr)); p1.socket = client_st; p1.t = &thrd1; p2.socket = client_st; p2.t = &thrd2; pthread_create(&thrd1, NULL, recvsocket, (void *)&p1); pthread_detach(thrd1);//设置线程可分离 pthread_create(&thrd2, NULL, sendsocket, (void *)&p2); pthread_detach(thrd2);//设置线程可分离} close(st);//关闭server端listen的socket return EXIT_SUCCESS;}
client端:
#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/socket.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <netinet/in.h>#include <arpa/inet.h>#include <pthread.h>//接收客户端的socket数据的线程void *recvsocket(void *arg){int st = *((int *)arg);char s[1024];while(1){memset(s, 0, sizeof(s));int rc = recv(st, s, sizeof(s), 0);if(rc <= 0)//如果recv小于等于0 代表socket已经关闭或者出错了{break;}else{printf("client:%s\n", s);}}return NULL;}void *sendsocket(void *arg)//向client端socket发送数据{int st = *((int *)arg);char s[1024];while(1){memset(s, 0, sizeof(s));read(STDIN_FILENO, s, sizeof(s));//读取用户输入信息send(st, s, strlen(s), 0);}return NULL;}//第二套int main(int arg, char *args[]){ if (arg < 3) { return -1; } char *ipv4 = args[1]; int port = atoi(args[2]);int st = socket(AF_INET, SOCK_STREAM, 0);//初始化socketif(st == -1){printf("create socket error:%s\n", strerror(errno));return -1;}struct sockaddr_in addr;//定义一个IP地址的结构memset(&addr, 0 , sizeof(addr));addr.sin_family = AF_INET;//设置结构地址类型为TCP/IP地址addr.sin_port = htons(port);//指定一个端口号 8900 htons: 将short类型从host字节类型到net字节类型的转化addr.sin_addr.s_addr = inet_addr(ipv4);//将字符串类型的IP地址转化为int,赋给addr结构成员//调用connect连接到结构addr指定的IP地址和端口号if(connect(st, (struct sockaddr *)&addr, sizeof(addr)) == -1){printf("connect failed %s\n", strerror(errno));return -1;}pthread_t thrd1, thrd2;pthread_create(&thrd1, NULL, recvsocket, (void *)&st);pthread_create(&thrd2, NULL, sendsocket, (void *)&st);pthread_join(thrd1, NULL);//pthread_join(thrd2, NULL);close(st);//关闭socketreturn EXIT_SUCCESS;}
makefile:
.SUFFIXES:.c .oCC=gccSRCS1=socket.cSRCS2=server.cOBJS1=$(SRCS1:.c=.o)OBJS2=$(SRCS2:.c=.o)EXEC1=socketEXEC2=serverstart: $(OBJS1) $(OBJS2)$(CC) -o $(EXEC1) $(OBJS1) -lpthread$(CC) -o $(EXEC2) $(OBJS2) -lpthread@echo '-----------OK-----------'.c.o:$(CC) -Wall -g -o $@ -c $<clean:rm -rf $(OBJS1) $(ONJS2)
0 0
- socket线程应用
- 线程池在socket通信中的应用
- socket线程池——ExecutorService应用
- socket 应用
- Socket 应用
- Socket应用
- socket应用
- Socket 应用
- socket应用
- socket应用
- Socket应用
- 线程应用
- socket 线程池
- 线程与socket句柄
- Linux Socket编程 线程
- Socket编程与线程
- socket 线程 思路 java
- socket 线程 思路 java
- $this->load->library()使用方法与心得
- 【算法概论】0.序言
- 如何重启服务
- 实验9 问题 E: 编写函数:各位数字之和 (Append Code)
- 如何搭建一个完整的视频直播系统?
- socket线程应用
- spring-data-redis整合
- DevOps状态,依赖脚本和IT自动化
- java:for循环删除集合元素的陷阱|浮点数相减少引起的误差|误用八进制|死循环|初始化静态成员变量的陷阱
- 子窗口的打开和关闭
- 手机网站的顶部或者底部固定浮动代码
- 面向对象下面几步
- test
- android 开发之安全问题