客户端和服务器实现全双工通信(基于线程)
Posted zzfx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了客户端和服务器实现全双工通信(基于线程)相关的知识,希望对你有一定的参考价值。
http://blog.sina.com.cn/s/blog_87766e4a0100yp7a.html
1、 基于多线程实现一个服务器和一个客户端实现全双工通信
服务器端创建两个线程:一个用于接收客户端发送过来的信息;一个用来给客户端发送信息。
客户端也创建两个线程:一个用于接收服务器端发送过来的信息;一个用来给服务器端发送信息。
2、 示例代码
服务器端的代码client.c
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#define SERVPORT 3333
#define BACKLOG 10 //请求队列中的最大请求数
#define MAX_CONNECTED_NO 10 //最大是128台电脑连接
#define MAXDATASIZE 100
void pthread_recv(void *arg);
void Pthread_send(void * arg);
int main()
{
struct sockaddr_in server_sockaddr,client_sockaddr;
int sockfd,client_fd,sin_size,ret;
pthread_t id1,id2;
sin_size =sizeof(struct sockaddr);
//struct sockaddr_in server_sockaddr,client_sockaddr;
//建立一个socket连接
//目前都是AF_INET(ipv4);SOCK_STREAM(TCP),如果是UDP,则SOCK_DGRAM
if((sockfd = socket(AF_INET,SOCK_STREAM,0))==-1){
perror("socket");
exit(1);
}
printf("socket success!,sockfd=%d\n",sockfd);
//bind用于本地IP地址和端口的绑定
server_sockaddr.sin_family=AF_INET;
server_sockaddr.sin_port=htons(SERVPORT);
server_sockaddr.sin_addr.s_addr=INADDR_ANY; //htonl(INADDR_ANY)
bzero(&(server_sockaddr.sin_zero),8);
//把本端的信息绑定
if(bind(sockfd,(struct sockaddr *)&server_sockaddr,sizeof(struct sockaddr))==-1)
{
perror("bind");
exit(1);
}
printf("bind success!\n");
if(listen(sockfd,BACKLOG)==-1)
{
perror("listen");
exit(1);
}
printf("listening....\n");
//接受并保存客户端的信息
if((client_fd=accept(sockfd,(struct sockaddr *)&client_sockaddr,&sin_size))==-1)
{
perror("accept");
exit(1);
}
printf("client_fd=%d",client_fd);
pthread_create(&id1,NULL,(void *) pthread_recv,(void*)&client_fd);
if(ret != 0)
perror("pthread_recv creat");
ret=pthread_create(&id2,NULL,(void *)Pthread_send,(void*)&client_fd);
if(ret != 0)
perror("Pthread_send creat");
pthread_join(id1,NULL);
pthread_join(id2,NULL);
close(sockfd);
}
//服务器发送线程
void Pthread_send(void * arg)
{
int buf_len, client_fd,sendbytes;
char buf[MAXDATASIZE];
client_fd = *((int *)arg);
printf("server send: ");
while(1)
{
fgets(buf,MAXDATASIZE,stdin);
buf_len =sizeof(buf);
if((sendbytes = send(client_fd ,buf,buf_len,0))==-1)
{
perror("send");
exit(1);
}
if(!strncmp(buf,"end",3)) //只比较字符串的前三个字符
break;
sleep(2);
}
}
//服务器接收数据线程
void pthread_recv(void *arg)
{
int buf_len, client_fd,recvbytes;
char buf[MAXDATASIZE];
client_fd = *((int *)arg);
//接收服务端发来的信息
while(1)
{
if((recvbytes = recv(client_fd ,buf,MAXDATASIZE,0))==-1)
{
perror("recv");
exit(1);
}
else
{
buf[recvbytes]=0;
printf("server received data from server is :%s\n",buf);
if(!strncmp(buf,"end",3)) //只比较字符串前三个字符
break;
}
sleep(1);
}
}
客户端的代码:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define SERVPORT 3333
#define MAXDATASIZE 100
void pthread_recv(void *arg);
void Pthread_send(void * arg);
main(int argc,char *argv[]){
int sockfd,sin_size,ret;
struct hostent *host;
pthread_t id1,id2;
struct sockaddr_in serv_addr; //套接字的地址结构
struct sockaddr_in server_sockaddr;
if(argc < 2)
{
fprintf(stderr,"Please enter the server‘s hostname!\n");
exit(1);
}
//AF_INET:使用的是IPV4
//SOCK_STREAM:流式套接字
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket");
exit(1);
}
printf("sockfd=%d\n",sockfd);
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERVPORT);
//serv_addr.sin_addr=*((struct in_addr *)host->h_addr);
//host->h_addr强制类型转换;建议直接使用下面的方法
serv_addr.sin_addr.s_addr=inet_addr(argv[1]); //"127.0.0.1"); Internet地址
bzero(&(serv_addr.sin_zero),8);
//连接
if(connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(struct sockaddr))==-1)
{
perror("connect");
exit(1);
}
ret=pthread_create(&id1,NULL,(void *)Pthread_send,(void*)&sockfd);
if(ret != 0)
perror("Pthread_send creat");
pthread_create(&id2,NULL,(void *) pthread_recv,(void*)&sockfd);
if(ret != 0)
perror("pthread_recv creat");
pthread_join(id1,NULL);
pthread_join(id2,NULL);
close(sockfd);
}
//客户端发送数据线程
void Pthread_send(void * arg)
{
int buf_len, sockfd,sendbytes;
char buf[MAXDATASIZE];
sockfd = *((int *)arg);
printf("client send: ");
while(1)
{
fgets(buf,MAXDATASIZE,stdin);
buf_len =sizeof(buf);
if((sendbytes = send(sockfd,buf,buf_len,0))==-1)
{
perror("send");
exit(1);
}
if(!strncmp(buf,"end",3)) //只比较字符串的前三个字符
break;
sleep(2);
}
}
//客户端接收数据线程
void pthread_recv(void *arg)
{
int buf_len, sockfd,recvbytes;
char buf[MAXDATASIZE];
sockfd = *((int *)arg);
//接收服务端发来的信息
while(1)
{
if((recvbytes = recv(sockfd,buf,MAXDATASIZE,0))==-1)
{
perror("recv");
exit(1);
}
else
{
buf[recvbytes]=0;
printf("client received data from server is :%s\n",buf);
if(!strncmp(buf,"end",3)) //只比较字符串的前三个字符
break;
}
sleep(1);
}
}
以上是关于客户端和服务器实现全双工通信(基于线程)的主要内容,如果未能解决你的问题,请参考以下文章