嵌入式每日学习心得 基于TCP/IP的聊天室程序
来源:互联网 发布:fp系列编程手册 编辑:程序博客网 时间:2024/05/16 08:50
//cilent.c#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <unistd.h>#include <pthread.h>void* rcv_fun(void* arg);int main(int argc,char *argv[]){ //FILE* p =fopen("1.txt","w+"); //fclose(p); int sock = socket(AF_INET, SOCK_STREAM, 0); int opt_val = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof(opt_val)); struct sockaddr_in myaddr; myaddr.sin_family = AF_INET; myaddr.sin_addr.s_addr = INADDR_ANY; myaddr.sin_port = htons(1234); if(-1 == bind(sock,(struct sockaddr*)&myaddr, sizeof(myaddr))) { perror("bind"); exit(-1); } struct sockaddr_in srv_addr; srv_addr.sin_family = AF_INET; srv_addr.sin_addr.s_addr = inet_addr(argv[1]); srv_addr.sin_port = htons(atoi(argv[2])); if(-1 == connect(sock,(struct sockaddr*)&srv_addr,sizeof(srv_addr))) { perror("connect"); exit(-1); } pthread_t tid; int num; char buf[2048]; struct timeval rcv_timeout; rcv_timeout.tv_sec = 0; rcv_timeout.tv_usec = 100000; //setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &rcv_timeout, sizeof(rcv_timeout)); if(0 != pthread_create(&tid, NULL, rcv_fun, (void*)sock)) { perror("pthread_create"); exit(-1); } while(1) { //printf("本机:"); //scanf("%s",buf); //fgets(buf,100,stdin); gets(buf); if(-1 == send(sock,buf,strlen(buf),0)) { perror("send"); } fflush(stdin); } close(sock); return 0;}void* rcv_fun(void* arg){ char buf[2048]; int num; pthread_detach(pthread_self()); int sock =(int)arg; while(1) { num = recv(sock ,buf, sizeof(buf), 0); if(num <= 0) { printf("接受数据失败,连接断开!\n"); } else { buf[num] = '\0'; printf("%s\n",buf); } } return NULL;}//server.c#include <stdio.h>#include <stdlib.h>#include <string.h>#include <arpa/inet.h>#include <pthread.h>#include <sys/types.h>#include <sys/socket.h>#include <signal.h>#include <unistd.h>void* con_fun(void* arg);struct buff{int sock_in;struct sockaddr_in addr;};pthread_mutex_t m;int main(){ FILE* p =fopen("1.txt","w+"); fclose(p); signal(SIGPIPE,SIG_IGN);pthread_mutex_init(&m,NULL);int sock_fp=socket(AF_INET,SOCK_STREAM,0);int opt_val;setsockopt(sock_fp,SOL_SOCKET,SO_REUSEADDR,&opt_val,sizeof(opt_val));struct sockaddr_in myaddr;myaddr.sin_family=AF_INET;myaddr.sin_addr.s_addr=INADDR_ANY;myaddr.sin_port=htons(9999);if(-1==bind(sock_fp,(struct sockaddr*)&myaddr,sizeof(myaddr))){perror("bind");exit(-1);}if(-1==listen(sock_fp,5)){perror("listen");exit(-1);}pthread_t tid;int sock_conn;struct sockaddr_in silent_addr;socklen_t len;int tag[]={0}; FILE* q;while(1){len=sizeof(silent_addr);struct buff* s1=(struct buff*)malloc(sizeof(struct buff)); sock_conn=accept(sock_fp,(struct sockaddr*)&silent_addr,&len); printf("sock_conn:%d",sock_conn);if(sock_conn==-1){perror("accept");continue;}s1->sock_in=sock_conn;s1->addr=silent_addr;pthread_mutex_lock(&m);FILE* fp=fopen("1.txt","a+"); int i=0,j=0; q=fopen("1.txt","r"); while(!feof(q)) { fscanf(q,"%d\n",&tag[i++]); } for(j=0;j<=i;j++) { if(s1->sock_in == tag[j]) break; if(j==i) fprintf(fp,"%d\n",sock_conn); } //fprintf(fp,"%d\n",sock_conn);fclose(fp); fclose(q);pthread_mutex_unlock(&m);if(0!=pthread_create(&tid,NULL,con_fun,s1)){perror("pthread_create");close(sock_conn);}} system("rm 1.txt");close(sock_fp);pthread_mutex_destroy(&m);return 0;}void* con_fun(void* arg){pthread_detach(pthread_self());struct buff s1=*((struct buff*)arg);free(arg);char msg[100]; char buf[100];int ret;int sock;while(1){ret=recv(s1.sock_in,msg,sizeof(msg)-1,0);if(ret>0){msg[ret]='\0'; sprintf(buf,"%s:%d:%s",inet_ntoa(s1.addr.sin_addr),ntohs(s1.addr.sin_port),msg);}else{printf("接收失败\n"); break;}pthread_mutex_lock(&m);FILE* fp=fopen("1.txt","r");while(!feof(fp)){ fscanf(fp,"%d\n",&sock); printf("sock:%d\n",sock);if(sock!=s1.sock_in)send(sock,buf,strlen(buf),0);}fclose(fp);pthread_mutex_unlock(&m);}close(s1.sock_in);return NULL;}
基于TCP协议编程{
//TCP编程步骤
服务器端 客户端
1.创建套接字 socket() 1.创建套接字 socket()
2.套接字与端口的绑定 bind() (客户端也可套接字和端口绑定,但一般没有这个必要)
3.设置监听队列 listen()
4.接收客户端连接 accept() 2.连接服务器 connect()
5.收发数据 recv() write() 3.收发数据
6.断开 close() 4.断开
一方调用close函数只是断开一半连接
设置地址复用{
int optval=1;
setsockopt(sock_listen,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval));
setsockopt: 设置套接字的某个属性值
设置sock_listen套接字的SO_REUSEADDR属性值为1,以让它可以地址复用
}
2.基于TCP协议通信中的粘包问题{
粘包问题产生的原因:
1.发送方造成的:TCP协议为了提升传输效率,在默认情况下,在我们调用send函数发送一份数据时,系统并不会将这份数据立即打包发送到网络上去,而只是将这份数据存放到网络发送缓冲区中,然后等待一小段时间,如果在这段时间之内我们又调用send函数发送数据,那么系统会进行同样的处理,如果我们在这段时间之内没有对外发送数据,那么系统会将网络发送缓冲区中的所有数据打成一个数据包发送到网络上去
2.接收方造成的:如果接收方不及时接收对方发送过来的多个数据包,那么这多个数据包将会在接收方的网络接收缓冲区中合并在一起,此时如果接收方提供一个足够大的缓冲区来接收这些数据,那么将会一次性接收到所有数据包的数据
粘包问题解决方案:
1.增加连续发送间隔时间(usleep):非常草根,严重影响效率
2.取消TCP内部的那个优化算法:不推荐,不是所有平台支持
3.加包头或包尾
4.应答式通信
}
阅读全文
0 0
- 嵌入式每日学习心得 基于TCP/IP的聊天室程序
- 基于嵌入式TCP/IP的实时数据传输
- Unity基于TCP/IP的小聊天室实现
- 基于TCP的C#开发的聊天室C/S程序
- JAVA 基于TCP协议编写的Socket聊天室程序
- 【PyQt4 实例20】基于TCP网络的聊天室程序
- 嵌入式每日学习心得 网络通信技术(TCP)
- Java基于TCP的聊天室
- 基于TCP协议的聊天室
- 嵌入式每日学习心得 线程
- 基于ARM的嵌入式TCP/IP协议的实现
- 基于ARM的嵌入式TCP/IP协议的实现
- 基于ARM的嵌入式TCP/IP协议的实现
- 基于ARM的嵌入式TCP/IP协议的实现方法
- 基于ARM的嵌入式TCP/IP协议的实现
- 基于epoll的聊天室程序
- 基于epoll的聊天室程序
- 【tcp-ip学习总结】基于udp的多人聊天室,带有登录注册功能
- 二分答案-----noip2015 跳石头
- js方法的重写和重载
- java Comparable接口与Comparator接口的使用与区别
- ACM ICPC 乌鲁木齐网络赛 J. Our Journey of Dalian Ends
- 笔试_java基础3
- 嵌入式每日学习心得 基于TCP/IP的聊天室程序
- 说说个人对Struts,Spring,Hibernate分别是什么的理解
- Armadillo矩阵库的使用(二)之API接口
- WebService
- java 集合框架
- struts2类型转换失败后的处理
- ProcessDefinition是干这个用的
- 2017.9.9网易校招笔试最后一道编程解答
- Css网页中属性的操作,缩放,旋转,图片倾斜