前言
本期主要分享的是使用TCP网络编程实现双向通信的功能,也就是通信双方都能够同时进行消息的收发,这也是我们在平时遇到的最为经典的一种通信方式;
一、功能
通信双方都能够同时进行消息的收发,每一方都有两个线程,一个进行数据发送,另一个负责数据接收;
二、具体实现过程
1.引入库
头文件如下:
#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#endif
2.两个通信过程
2.1 A TO B
代码如下(示例):
#include "head.h"
struct sockaddr_in sendaddr;
pthread_t tid1;
pthread_t tid2;
int sockfd = 0;
void *sendfun(void *arg)
{
char tmpbuff[1024] = {0};
int ret = 0;
ssize_t nsize = 0;
while (1)
{
fgets(tmpbuff, sizeof(tmpbuff), stdin);
tmpbuff[strlen(tmpbuff) - 1] = 0;
nsize = send(sockfd, tmpbuff, sizeof(tmpbuff), 0);
if (nsize <= 0)
{
perror("fail to send");
return NULL;
}
if (!strcmp(tmpbuff, "q"))
{
break;
}
}
close(sockfd);
pthread_cancel(tid2);
return NULL;
}
void *recvfun(void *arg)
{
char tmpbuff[1024] = {0};
ssize_t nsize = 0;
while (1)
{
nsize = recv(sockfd, tmpbuff, sizeof(tmpbuff), 0);
if (nsize <= 0)
{
perror("fail to recv");
return NULL;
}
if (!strcmp(tmpbuff, "q"))
{
break;
}
printf("recv:%s\n", tmpbuff);
}
close(sockfd);
pthread_cancel(tid1);
return NULL;
}
int main(int argc, const char *argv[])
{
int ret = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == sockfd)
{
perror("fail to sockfd");
return -1;
}
sendaddr.sin_family = AF_INET;
sendaddr.sin_port = htons(50000);
sendaddr.sin_addr.s_addr = inet_addr("192.168.209.129");
ret = connect(sockfd, (struct sockaddr *)&sendaddr, sizeof(sendaddr));
if (-1 == ret)
{
perror("fail to connect");
return -1;
}
pthread_create(&tid1, NULL, sendfun, NULL);
pthread_create(&tid2, NULL, recvfun, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
2.2 B TO A
#include "head.h"
struct sockaddr_in sendaddr;
pthread_t tid1;
pthread_t tid2;
int confd = 0;
void *sendfun(void *arg)
{
char tmpbuff[1024] = {0};
int ret = 0;
ssize_t nsize = 0;
while (1)
{
fgets(tmpbuff, sizeof(tmpbuff), stdin);
tmpbuff[strlen(tmpbuff) - 1] = 0;
nsize = send(confd, tmpbuff, sizeof(tmpbuff), 0);
if (nsize <= 0)
{
perror("fail to send");
return NULL;
}
if (!strcmp(tmpbuff, "q"))
{
break;
}
}
close(confd);
pthread_cancel(tid2);
return NULL;
}
void *recvfun(void *arg)
{
int ret = 0;
char tmpbuff[1024] = {0};
ssize_t nsize = 0;
while (1)
{
nsize = recv(confd, &tmpbuff, sizeof(tmpbuff), 0);
if (nsize <= 0)
{
perror("fail to recv");
return NULL;
}
if (!strcmp(tmpbuff, "q"))
{
break;
}
printf("recv:%s\n", tmpbuff);
}
close(confd);
pthread_cancel(tid1);
return NULL;
}
int main(int argc, const char *argv[])
{
int ret = 0;
int sockfd = 0;
struct sockaddr_in recvaddr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == sockfd)
{
perror("fail to sockfd");
return -1;
}
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(50000);
recvaddr.sin_addr.s_addr = inet_addr("192.168.209.129");
ret = bind(sockfd, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
if (-1 == ret)
{
perror("fail to bind");
return -1;
}
ret = listen(sockfd, 10);
if (-1 == ret)
{
perror("fail to sockfd");
return -1;
}
confd = accept(sockfd, NULL, NULL);
if (-1 == confd)
{
perror("fail to accept");
return -1;
}
pthread_create(&tid1, NULL, sendfun, NULL);
pthread_create(&tid2, NULL, recvfun, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
3 TCP在进行双向通信时与UDP的对比
(1)UDP是面向数据包的通信方式;要想双方通信必须绑定各自的IP地址和端口号;要么只绑定一方,但是此时若想实现双方通信,就需要另一方接收发送端的struct sockaddr *的结构体(也就是发送端的IP地址以及端口号),进而进行收发;
(2)TCP的特点是面向链接的通信方式;所以最重要的就是建立链接,发送端创建套接字直接进行connect,接收端listen,accept后生成新的通信文件描述符进行通信;所以TCP通信方式既可靠又简便,但是在实现机制比较复杂;比如TCP链接时需要进行三次握手请求,断开时需要进行四次挥手操作;
总结
本期分享的主要是使用TCP的函数接口实现TCP的网络编程实现双方通信的功能,与以前分享的一个UDP实现双方通信的实例对比得出了两者的一些不同点,更深一步掌握了网络编程的技术知识;希望各位小伙伴认真阅读,一起进步,加油哟!
最后,各位小伙伴们如果喜欢我的分享可以点赞收藏哦,你们的认可是我创作的动力,一起加油!