基于UDP的socket客户服务器编程

前面我们写了关于TCP的客户/服务器模式,现在我们写关于UDP的客户/服务器模式。

基于TCP编写的应用程序和基于TCP编写的应用程序之间存在一些本质的差异,其原因在于这两个传输层之间的差别:UDP是无连接不可靠的数据报协议,不同于TCP提供的面向连接的可靠字节流。

我们先来说一下简单的模型:在基于UDP的应用程序中,客户不与服务器建立连接,而只是使用sendto函数给服务器发送数据报,其中必须指定目的地(即服务器)的地址作为参数。当然,在服务器端不接受来自客户的连接,只是使用recvfrom函数,等待来自某个客户的数据到达。

接下来我们来说说将要用到的两个重要的函数:

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

其中前3个参数分别就是我们所创建的套接字描述符,指向读入或写出的缓冲区指针和读写字节数;

第4个参数我们当下暂时赋值为0;

第5个参数src_addr指向一个将由该函数在返回时填写数据报发送者的协议地址的套接字地址结构,而在该套接字地址结构中填写的字节数则放在addrlrn参数所指定的整数中返回给调用者。

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);

前三个参数和recvfrom参数一样;

第4个参数指向一个含有数据包接收者的协议地址(IP地址及端口号)的套接字地址结构,其大小同样由第6个参数决定。

注意:sendto最后一个参数是一个整数值,而recvfrom的最后一个参数是一个指向整数值的指针(即输入输出形参数)。recvfrom的最后两个参数类似于accept的最后两个参数,返回时其中套接字地址结构的内容告诉我们是谁发送了数据报(UDP)或是谁发起了连接(TCP)。sendto的最后两个参数类似于connect的最后两个参数,调用时其中套接字地址结构被我们填入数据报将发往(UDP)或与之建立连接(TCP)的协议地址。

下面我们来具体看看代码:

服务器端:

 #include <stdio.h>
   #include <string.h>
   #include <errno.h>
   #include<stdlib.h>
   #include <netinet/in.h>
   #include <arpa/inet.h>
   #include <sys/types.h>
   #include <sys/socket.h>
   
  void usage(const char* arg)
  {
      printf("%s [ip][port\n",arg);
  }
  
  int main(int argc,char *argv[])
  {
      if(argc != 3)
      {
          usage(argv[0]);
          exit(0);
      }
  
      int port=atoi(argv[2]);
      char *ip=argv[1];
  
      int sock=socket(AF_INET,SOCK_DGRAM,0);//面向数据报
      if(sock<0)
      {
          perror("socket");
          exit(1);
      }
  
      struct sockaddr_in local;                                                                                                                                       
      local.sin_family=AF_INET;
      local.sin_port=htons(port);
      local.sin_addr.s_addr=inet_addr(ip);
      local.sin_port=htons(port);
      local.sin_addr.s_addr=inet_addr(ip);
  
      if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
      {
          perror("bind");                                                                                                                                             
          exit(2);
      }
  
      struct sockaddr_in client;
      socklen_t len=sizeof(client);
      char buf[1024];
      while(1)
      {
          memset(buf,‘\0‘,sizeof(buf));
          ssize_t _s =recvfrom(sock,buf,sizeof(buf)-1,0,(struct sockaddr*)&client,&len);
          if(_s>0)
          {
              buf[_s]=‘\0‘;
              printf("[%s %d]#:%s",inet_ntoa(client.sin_addr),ntohs(client.sin_port),buf);
          }
         else if(_s == 0)
          {
              printf("client close...\n");
              break;
          }
          else{//recv fail
  
          }
      }
      return 0;
  }

再来看看客户端:

void usage(const char* arg)
  {
      printf("%s [remote_ip][remote_port\n",arg);
  }
  
  int main(int argc,char *argv[])
  {
      if(argc != 3)
      {
          usage(argv[0]);
          exit(0);
      }
  
      int port=atoi(argv[2]);
      char *ip=argv[1];                                                                                                                                               
  
      int sock=socket(AF_INET,SOCK_DGRAM,0);//面向数据报
      if(sock<0)
      {
          perror("socket");
          exit(1);
      }
  
      struct sockaddr_in remote;
      remote.sin_family=AF_INET;
      remote.sin_port=htons(port);
      remote.sin_addr.s_addr=inet_addr(ip);
  
      char buf[1024];
      while(1)
      {
          printf("please enter: ");
          fflush(stdout);
          ssize_t _s=read(0,buf,sizeof(buf)-1);
          buf[_s]=‘\0‘;
          _s=sendto(sock,buf,strlen(buf),0,(struct sockaddr*)&remote,sizeof(remote));
      }
      return 0;
  }

运行结果如下:

上图测试是在一台主机的情况下,我们可以看到客户端发送的消息被服务端收到了,实现了基于UDP的简单通信。

时间: 2024-12-17 22:08:04

基于UDP的socket客户服务器编程的相关文章

基于UDP的Socket网络编程实现用户登录的实现

package Test_UDP_Socket; import java.net.DatagramPacket.* //服务器端 import java.net.DatagramSocket; import java.net.InetAddress; public class ServerUDP { public static void main(String[] args) throws Exception{ //1.先实现接收Client信息 DatagramSocket socketSer

基于UDP的socket编程

一.相关函数说明 UDP是无连接的,即发送数据之前不需要建立连接. 除了基于TCP中的socket编程所需的函数之外,基于UDP的socket编程中还需要用到两个函数. 1.sendto函数:用于客户端中指定一目的地发送数据. (1)函数原型 (2)参数说明 sockfd:套接字 buf:待发送数据的缓冲区 len:缓冲区长度 flags:调用方式标志位,一般为0:若改变flags,则sendto发送数据的形式会变成阻塞 dest_addr:指向目的套接字的地址 addrlen:指向目的套接字的

[java]基于UDP的Socket通信Demo

java课编程作业:在老师给的demo的基础上实现客户端发送数据到服务器端,服务器端接受客户端后进行数据广播. 整体功能类似于聊天室,代码部分不是太难,但是在本机测试的时候出现这样的问题: 服务端通过将每一个Socket客户端的IP存入Set集合,每次接受到数据后都向当前所有的IP转发.但是本机演示的时候所有开的ChatClient客户端都是同一IP,怎么测试呢? 解决办法就是本机测试时候服务端向多个不同的端口转发就好了,这样跑起来的客户端是在不同端口上进行监听的(只是为了实现广播,实际应用下还

recv原理、高阶版黏包解决方案、基于UDP的socket通信

recv原理.高阶版黏包解决方案.基于UDP的socket通信 recv原理 源码解释: Receive up to buffersize bytes from the socket. 接收来自socket缓冲区的字节数据, For the optional flags argument, see the Unix manual. 对于这些设置的参数,可以查看Unix手册. When no data is available, block untilat least one byte is av

Java中基于UDP协议的的网络编程(基础篇)

---恢复内容开始--- 一:什么是网络编程? 通俗的来说, 网络编程就是编写程序,让联网的两个或多个设备(例如计算机)之间进行数据传输.Java语言也支持网络编程,JDK提供的 java.net包提供了很多于网络编程相关的类,来支持网络编程方面的学习. 二:java网络编程所使用的协议? 有了计算机网络的基础,我们不难理解,在java中,网络编程是基于网络传输协议的. java网络编程,可以是基于TCP协议的,也可以基于UDP协议的.那么首先我们得知道tcp协议和udp两种协议的区别. 区别:

TCP客户/服务器编程入门

最近在学习UNP,特此记录. 1. TCP回射服务器程序 #include "unp.h" void str_echo(int sockfd) { ssize_t n; char buf[MAXLINE]; again: while ( (n = read(sockfd, buf, MAXLINE)) > 0) Writen(sockfd, buf, n); if (n < 0 && errno == EINTR) goto again; else if (

基于java的socket简单聊天编程

socket编程: 一:什么是socket:socket是BSD UNIX的通信机制,通常称为“套接字”,其英文原意是“孔”或“插座”.有些顾名思义,socket正如其英文原意一样,像是一个多孔插座,可以提供多个端口的连接服务.为了更加直观的了解socket,可以用插座来比喻socket.如果说socket是一个多孔插座,插座是提供各种电器供电的地方,不同的电器工作时需要的电压和电流也不一样,但各种电器都有各自的一个插口,这个称之为“端口”.电器使用的电可以看做是网络资源或者是各种“流”,电是由

基于udp的socket

服务端 #udp叫用户数据报协议,它不会出现粘包形象,但会出现信息缺失#udp服务端单进程'''import socket udpserver =socket.socket(socket.AF_INET,socket.SOCK_DGRAM)ip_port =('127.0.0.1',8083)udpserver.bind(ip_port) #绑定手机卡,即确定服务器,udp只管收发信息,不必管对方是否确认了.即不必建立管道,#同时也不会等待对方是否发送信息while True: #通信循环 da

network programming-简单的TCP客户服务器编程

简单的TCP程序客户端流程:创建套接字(套接字用IP地址:端口号)表示)socket()->请求连接connect()->交换数据 send()/recv()->关闭连接 closesocket() 简单的TCP程序服务端流程:创建套接字socket()->绑定相应的端口bind()->监听端口listen()->接受连接accept()->交换数据recv()/send()->关闭连接 closesocket() 第一个网络程序 代码实现: TcpServ