TCP和UDP的代码实现

📅 2026/6/16 16:45:13
TCP和UDP的代码实现
引言本片文章是基于一定网络编程基础来实现的TCP和UDP的基本架构实现了服务端和客户端的代码TCP对于TCP来说它的优势就是在于对于传递信息十分的准确因为它存在了三次握手和四次挥手的机制但是缺点也就是每一次信息的传递要消耗大量的资源来保证每一次传递信息的准确性。我们可以简单的模拟一下TCP通信的过程方便我们代码的构架首先作为服务器我们应该先创建一个套接字socket接受来自客户端那一边的连接请求。但是套接字这个仅仅是一个载体这个载体就是属于谁性质是什么都没有确定所以服务器必须要绑定bind这一个载体然后当一切准备就绪了之后服务器就要开始监听listen因为我们创建载体的目的就是为了监听客户端。这个监听是存在一个队列的也就是如果有多个客户端请求服务器那么这些客户端就会放在这个等待队列里面等待这服务器的处理。我们一般设置这个队列的长度是128。然后当我们服务器从队列里面取出一个任务的时候accept就会创建出一个新的套接字这个套接字和最开始的不是一个东西这个是专门用来和取出来的客户端进行沟通的然后沟通的方式就是recv和send作为数据的收发~~~然后作为客户端我们不需要监听而是connect因为客户端是连接服务器的。这个是服务器端首先就是sin结构体的初始化我们选择的是ipv4TCP通信地址是本机的地址#include iostream #include sys/socket.h #include netinet/in.h #include arpa/inet.h #include unistd.h #include string.h #define SER_PORT 8888 #define SER_IP 192.168.189.134 int main() { int sfd socket(AF_INET, SOCK_STREAM, 0); if (sfd -1) { perror(socket error); return -1; } sockaddr_in sin; sin.sin_family AF_INET; sin.sin_port htons(SER_PORT); sin.sin_addr.s_addr inet_addr(SER_IP); if(bind(sfd, (struct sockaddr *) sin, sizeof(sin)) -1) { perror(bind error); return -1; } if(listen(sfd, 128) -1) { perror(listen error); return -1; } sockaddr_in cin; socklen_t sockLen sizeof(cin); int newfd accept(sfd, (struct sockaddr *) cin, sockLen); if (newfd -1) { perror(accept error); return -1; } char rbuf[1024]; while(1) { bzero(rbuf, sizeof(rbuf)); int res recv(newfd, rbuf, sizeof(rbuf), 0); // 阻塞接受数据 if(res -1) { perror(recv error); return -1; } if(res 0) { std::cout client close std::endl; break; } strcat(rbuf,*_*); if(send(newfd, rbuf, strlen(rbuf), 0) -1) { perror(send error); return -1; } } close(newfd); close(sfd); return 0; }然后对于客户端我们其实不需要填写cin的任何信息因为我们只需要连接客户端然后发送信息或者接受信息服务器不需要知道我们客户端的信息所以bind也是不需要的不过写了也没错主要是通过socket这个套接字来和服务器联系。#include iostream #include sys/socket.h #include netinet/in.h #include arpa/inet.h #include unistd.h #include string.h #define SER_PORT 8888 #define SER_IP 192.168.189.133 #define CLI_PORT 9999 #define CLI_IP 192.168.189.133 int main() { int cfd socket(AF_INET, SOCK_STREAM, 0); if (cfd -1) { perror(socket error); return -1; } sockaddr_in cin; cin.sin_family AF_INET; cin.sin_port htons(CLI_PORT); // 客户端的地址可以选择不写因为客户端是主动连接别人的 if (bind(cfd, (struct sockaddr *) cin, sizeof(cin)) -1) { perror(bind error); return -1; } sockaddr_in sin; sin.sin_family AF_INET; sin.sin_port htons(SER_PORT); sin.sin_addr.s_addr inet_addr(SER_IP); if(connect(cfd, (struct sockaddr *) sin, sizeof(sin)) -1) { perror(connect error); return -1; } char wbuf[128] ; while(1) { bzero(wbuf, sizeof(wbuf)); fgets(wbuf, sizeof(wbuf), stdin); wbuf[strlen(wbuf) - 1] 0; if (send(cfd, wbuf, strlen(wbuf), 0) -1) { std::cout send error std::endl; break; } if (recv(cfd, wbuf, sizeof(wbuf), 0) -1) { std::cout recv error std::endl; break; } std::cout wbuf std::endl; } close(cfd); return 0; }UDPUDP的特点就是保证信息传递要快不是很看重信息的准确性所以UDP是面向无连接的也就是说不管你在不在线只要我知道你的地址不需要连接就可以直接把信息发送过去。所以缺点也就是信息可能会出现错误这种通信一般就是在广播方面的应用服务器端这一部分TCP有区别首先就是必须要传递cin也就是客户端的信息但是这个cin不需要初始化当客户端那边连接了服务器端之后cin就会接受客户端的数据然后进行通信。这个过程中如果客户端下线了服务器端的recvfrom会阻塞等待sendto仍然会发出信息因为UDP是面向无连接的不需要知道客户端是否在线。#include myhead.h #define SER_PORT 8888 #define SER_IP 192.168.189.133 int main(int argc, char const *argv[]) { //1、创建用于通信的套接字文件描述符 int sfd socket(AF_INET,SOCK_DGRAM,0); if(sfd -1){ perror(socket error); return -1; } printf(socket success sfd %d\n,sfd); //2、绑定ip地址和端口号 struct sockaddr_in sin; sin.sin_addr.s_addr inet_addr(SER_IP); sin.sin_family AF_INET; sin.sin_port htons(SER_PORT); if(bind(sfd,(struct sockaddr*) sin,sizeof(sin)) -1){ perror(bind error); return -1; } printf(bind success\n); //3、数据收发 char rbuf[128] ; //定义容器接受对端的地址信息结构体 struct sockaddr_in cin; socklen_t socklen sizeof(cin); while(1){ bzero(rbuf,sizeof(rbuf)); //从客户端中读取消息 if(recvfrom(sfd,rbuf,sizeof(rbuf),0,(struct sockaddr*)cin, socklen) -1){ perror(recvfrom error\n); return -1; } printf([%s : %d] : %s\n,inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),rbuf); //加个笑脸发给对方 strcat(rbuf,*_*); //将数据发送给客户端 sendto(sfd,rbuf,strlen(rbuf),0,(struct sockaddr*)cin,sizeof(cin)); printf(发送成功\n); } //4、关闭套接字 close(sfd); return 0; }这是客户端的代码因为没有connect函数了所以这里我们发送信息的时候需要传递sin的结构体保证客户端知道这个数据要传递给谁。但是至于接受数据其实nullptr就可以因为接收数据并不需要知道服务器的信息。#include iostream #include sys/socket.h #include netinet/in.h #include arpa/inet.h #include unistd.h #include string.h #define CLI_PORT 9999 #define SER_PORT 8888 #define SER_IP 192.168.189.134 #define CLI_IP 192.168.189.134 int main() { int cfd socket(AF_INET, SOCK_DGRAM, 0); if (cfd -1) { perror(socket error); return -1; } sockaddr_in cin; cin.sin_family AF_INET; cin.sin_port htons(CLI_PORT); cin.sin_addr.s_addr inet_addr(CLI_IP); if (bind(cfd, (struct sockaddr *) cin, sizeof(cin)) -1) { perror(bind error); return -1; } char wbuf[128] ; sockaddr_in sin; sin.sin_addr.s_addr inet_addr(SER_IP); sin.sin_port htons(SER_PORT); sin.sin_family AF_INET; while(1) { bzero(wbuf, sizeof(wbuf)); fgets(wbuf, sizeof(wbuf), stdin); wbuf[strlen(wbuf) - 1] 0; sendto(cfd, wbuf, strlen(wbuf), 0, (struct sockaddr *) sin, sizeof(sin)); recvfrom(cfd, wbuf, sizeof(wbuf), 0, nullptr, nullptr); std::cout wbuf std::endl; } close(cfd); return 0; }总结本片文章到这里就结束了希望可以帮助大家对两种通信方式有更好的理解~~~