TCP通信—客户端与客户端的双向通信

功能:

1.实现客户端与客户端之间的TCP双向通信;

2.服务器记录客户端实名连接,并显示客户端数据记录;

3.客户端退出,服务器和另一客户端显示相应提示;

服务器代码思路:

1.定义数组保存客户端文件描述符;

2.主程序负责接收客户端1的数据发送给客户端2;

3.开展一个线程负责接收到客户端2的信息发送给客户端1;

客户端代码思路:

1.建立socket连接

2.绑定IP和端口号

3.主动连接服务器

4.植入线程--TCP接收数据

5.TCP发送数据

服务器代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>

//定义客户端结构体
struct sockaddr_in client;

int sockfd;
int arr_fd[2];	//客户端文件描述符
char arr_ip[2][20];	//客户端IP数组

//TCP接收客户端2数据发送客户端1
void *show(void *arg){
    char buf[50];
    char buff[30] = "对方客户端已关闭!\n";
    while(1){
	bzero(buf,sizeof(buf));
	int ret = recv(arr_fd[1],buf,sizeof(buf),0);
	if(ret == 0 || ret < 0)//接收方向是客户端2的arr_fd
	{
	    sleep(1);
	    close(sockfd);
	    send(arr_fd[0],buff,sizeof(buff),0);
	    printf("客户端 %s 已关闭\n", arr_ip[1]);
	    break;
	}else if(ret < 0 || errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN){
	    continue;
	}
	send(arr_fd[0],buf,sizeof(buf),0);//向客户端1的arr_fd发送数据
	printf("客户端%s:%s\n",arr_ip[1],buf);
    }
}

int main(void)
{
    //建立socket连接
    sockfd=socket(AF_INET,SOCK_STREAM,0);//IPV4   TCP   0:前两个参生效
    if(sockfd<0){
	perror("socket");
	return -1;
    }
    printf("sockfd:%d\n",sockfd);    
    
    //声明服务器结构体
    struct sockaddr_in server;
    server.sin_family=AF_INET;//地址族  代表选择IPv4
    server.sin_port=htons(10086);//端口号 //因为有大小端序之分,所以要转换端序
    server.sin_addr.s_addr=inet_addr("192.168.90.116");//IP地址 点分十进制转化网络二进制
    
    //绑定IP和端口号
    if(bind(sockfd,(struct sockaddr *)&server,sizeof(server))){
	perror("bind");
	return -1;
    }

    //监听			
    listen(sockfd,8);

    //等待客户端连接
    int len = sizeof(client), i = 0;
    for(int i = 0; i < 2; i++){
	arr_fd[i] = accept(sockfd,(struct sockaddr *)&client,&len);
	if(arr_fd[i] < 0){
	    perror("accept");
	    return -1;
	}
	printf("客户%d上线\n",arr_fd[i]);
	strcpy(arr_ip[i],inet_ntoa(client.sin_addr));
	printf("其IP:%s PORT:%d\n",arr_ip[i],ntohs(client.sin_port));
    }

    //植入线程
	pthread_t tid2;
	pthread_create(&tid2,NULL,show,NULL);
	pthread_detach(tid2);//线程收尸

    //TCP接收客户端1数据发送客户端2
    char buf[50];
    char buff[30] = "对方客户端已关闭!\n";
    while(1){
	bzero(buf,sizeof(buf));
	int ret = recv(arr_fd[0],buf,sizeof(buf),0);
	if(ret == 0)//接收方向是客户端1的arr_fd
	{
	    sleep(1);
	    close(sockfd);
	    send(arr_fd[1], buff, sizeof(buff), 0);
	    printf("客户端 %s 已关闭\n", arr_ip[0]);
	    break;
	}else if(ret < 0 || errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN){
	    continue;
	}
	
	send(arr_fd[1],buf,sizeof(buf),0);//向客户端2的arr_fd发送数据
	printf("客户端%s:%s\n",arr_ip[0],buf);
    }

    return 0;
}

客户端代码:

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>

//实现双向通信	---线程
int fd;
void *show(void *arg){
    //接收
    int sockfd = *(int *)arg;
    char buf[50];
    while(1){
	bzero(buf, sizeof(buf));
	recv(sockfd,buf,sizeof(buf),0);
	printf("服务器: %s \n",buf);
    }
}

int main(void)
{
    //1.建立socket连接
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);//IPv4
    if(sockfd < 0){
	perror("socket");
	return -1;
    }
    printf("sockfd = %d\n", sockfd);

    //2.绑定IP和端口号
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(10086);
    server.sin_addr.s_addr = inet_addr("192.168.90.116");

    //3.主动连接
    if(connect(sockfd, (struct sockaddr *)&server, sizeof(server))){
	perror("socket");
	return -1;
    }

    //植入线程
    pthread_t tid;
    pthread_create(&tid, NULL, show, &sockfd);

    //5.TCP发送
    char buf[50];
    while(1){
	bzero(buf, sizeof(buf));
	scanf("%s", buf);
	send(sockfd,buf,sizeof(buf),0);
    }

    return 0;
}

运行结果:

 

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值