Linux下socket编程之UDP简单实现

来源:互联网 发布:西游记唐僧知乎 编辑:程序博客网 时间:2024/06/05 15:34

本文实现一个简单的UDP小例子,来说明Linux下socket编程之UDP的简单实现。本文主要包括三个部分:服务器端的实现,客服端的实现和通信测试。实现的功能:客服端发送一条消息给服务器端,服务器端把客服端发来的消息给显示出来。

一、服务器端的实现

1、打开一个socket用户服务器

/* 1、打开一个socket */iSocketServerFd = socket(AF_INET, SOCK_DGRAM, 0);// 网路类型为ipv4,链接类型为udp
2、将上面打开的socket与服务器进行绑定

/* 2、绑定 *//* 2.1 设置要绑定的服务器端 */tSocketServerAddr.sin_family      = AF_INET;// 网络类型为ipv4tSocketServerAddr.sin_port        = htons(SOCKET_PORT);// 设置服务器端口tSocketServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);memset(tSocketServerAddr.sin_zero, 0, 8);iSockAddrLen = sizeof(struct sockaddr);/* 2.2 对服务器端进行绑定 */iRet = bind(iSocketServerFd, (const struct sockaddr *)&tSocketServerAddr, iSockAddrLen);
3、接收客服端发送过来的数据

/* 3、接收数据 */iRecvLen = recvfrom(iSocketServerFd, ucRecvBuf, ARRAY_LENGTH, 0,                    (struct sockaddr *)&tSocketClientAddr, &iSockAddrLen);
服务器端实现的完整代码如下所示:
#include <stdio.h>#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>#include <string.h>#include <netinet/in.h>#include <arpa/inet.h>#include <signal.h>#define SOCKET_PORT1234// 定义socket绑定的端口#define LISTEN_BACKLOG10// 设置服务器最大的监听数量#define ARRAY_LENGTH256// 定义缓冲区的大小/*  * 接收客服端发送过来的数据,并把它们打印出来 */int main(void){int iSocketServerFd;// 定义服务器端的socket文件描述符int iSocketClientFd;// 定义客服端的socket文件描述符struct sockaddr_in tSocketServerAddr;struct sockaddr_in tSocketClientAddr;int iSockAddrLen;int iRet;unsigned char ucRecvBuf[ARRAY_LENGTH];// 定义接收缓冲区int iRecvLen;signal(SIGCHLD,SIG_IGN); /* 1、打开一个socket */iSocketServerFd = socket(AF_INET, SOCK_DGRAM, 0);// 网路类型为ipv4,链接类型为udpif(iSocketServerFd == -1){printf("socket error!\n");return -1;}/* 2、绑定 *//* 2.1 设置要绑定的服务器端 */tSocketServerAddr.sin_family      = AF_INET;// 网络类型为ipv4tSocketServerAddr.sin_port        = htons(SOCKET_PORT);// 设置服务器端口tSocketServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);memset(tSocketServerAddr.sin_zero, 0, 8);iSockAddrLen = sizeof(struct sockaddr);/* 2.2 对服务器端进行绑定 */iRet = bind(iSocketServerFd, (const struct sockaddr *)&tSocketServerAddr, iSockAddrLen);if(iRet == -1){printf("bind error!\n");return -1;}while(1){/* 3、接收数据 */iRecvLen = recvfrom(iSocketServerFd, ucRecvBuf, ARRAY_LENGTH, 0,                        (struct sockaddr *)&tSocketClientAddr, &iSockAddrLen);if(iRecvLen <= 0)// 失败{printf("recvfrom error!\n");close(iSocketServerFd);return -1;}else// 成功,将接收到的数据打印出来{ucRecvBuf[iRecvLen] = '\0';printf("Receive a message from : %s\n", inet_ntoa(tSocketClientAddr.sin_addr));printf("The message is : %s\n", ucRecvBuf);}}close(iSocketServerFd);return 0;}


二、客服端的实现
客服端的实现总体上来说分为两种方式:一种是先和服务器端进行链接然后在进行通信,另一种是直接进行通信。

2.1 先连接再通信

a、打开一个socket用于客服端

/* 1、打开一个socket用于客服端 */iSocketClientFd = socket(AF_INET, SOCK_DGRAM, 0);
b、连接

/* 2、connect *//* 2.1 设置链接的服务器端的基本信息 */tSocketServerAddr.sin_family      = AF_INET;// 网络类型为ipv4tSocketServerAddr.sin_port        = htons(SOCKET_PORT);// 服务器端的网络端口iRet = inet_aton(argv[1], &tSocketServerAddr.sin_addr);// 客服端的ip地址if(iRet == 0){printf("server ip is not valid!\n");return -1;}memset(tSocketServerAddr.sin_zero, 0, 8);iSockAddrLen = sizeof(struct sockaddr);/* 2.2 将服务器端和客服端链接起来 */iRet = connect(iSocketClientFd, (const struct sockaddr *)&tSocketServerAddr, iSockAddrLen);
c、发送数据

/* 3、将用户的输入发送给服务器端 */iSendLen = send(iSocketClientFd, ucSendBuf, strlen(ucSendBuf), 0);
完整的代码如下:
#include <stdio.h>#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>#include <string.h>#include <netinet/in.h>#include <arpa/inet.h>#define SOCKET_PORT1234// 设置服务器端的端口#define ARRAY_LENGTH256// 设置缓冲区的大小/* *输入一个字符串,发送给服务器端 */int main(int argc, char **argv){int iSocketClientFd;// 描述客服端socket的文件描述符struct sockaddr_in tSocketServerAddr;int iSockAddrLen;int iSendLen;unsigned char ucSendBuf[ARRAY_LENGTH];// 定义一个缓冲区int iRet;if(argc != 2){printf("Usage :\n");printf("%s <server_ip>\n", argv[0]);return -1;}/* 1、打开一个socket用于客服端 */iSocketClientFd = socket(AF_INET, SOCK_DGRAM, 0);if(iSocketClientFd == -1){printf("socket error!\n");return -1;}/* 2、connect *//* 2.1 设置链接的服务器端的基本信息 */tSocketServerAddr.sin_family      = AF_INET;// 网络类型为ipv4tSocketServerAddr.sin_port        = htons(SOCKET_PORT);// 服务器端的网络端口iRet = inet_aton(argv[1], &tSocketServerAddr.sin_addr);// 客服端的ip地址if(iRet == 0){printf("server ip is not valid!\n");return -1;}memset(tSocketServerAddr.sin_zero, 0, 8);iSockAddrLen = sizeof(struct sockaddr);/* 2.2 将服务器端和客服端链接起来 */iRet = connect(iSocketClientFd, (const struct sockaddr *)&tSocketServerAddr, iSockAddrLen);if(iRet == -1){printf("connect error!\n");return -1;}printf("Input a message to %s: \n", argv[1]);while(1){if(fgets(ucSendBuf, ARRAY_LENGTH, stdin))// 接收用户的输入{/* 3、将用户的输入发送给服务器端 */iSendLen = send(iSocketClientFd, ucSendBuf, strlen(ucSendBuf), 0);if(iSendLen <= 0){printf("send error!\n");close(iSocketClientFd);return -1;}}}close(iSocketClientFd);return 0;}

2.2 直接进行通信
a、打开socket

/* 1、打开客服端的socket */iSocketClientFd = socket(AF_INET, SOCK_DGRAM, 0);// 网络类型为ipv4, 传输类型为udp
b、发送数据

/* 2、强用户端的输入发送给服务器端 */iSendLen = sendto(iSocketClientFd, ucSendBuf, strlen(ucSendBuf), 0,               (const struct sockaddr *)&tSocketServerAddr, iSockAddrLen);
完整的代码实现如下:
#include <stdio.h>#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>#include <string.h>#include <netinet/in.h>#include <arpa/inet.h>#define SOCKET_PORT1234// 设置服务器端的网络端口#define ARRAY_LENGTH256// 设置缓冲区的大小/* *从用户端输入一个字符串,并把这个字符串发送给客服端 */int main(int argc, char **argv){int iSocketClientFd;// 定义一个表示客服端socket的文件描述符struct sockaddr_in tSocketServerAddr;int iSockAddrLen;int iSendLen;unsigned char ucSendBuf[ARRAY_LENGTH];// 定义缓冲区int iRet;if(argc != 2){printf("Usage :\n");printf("%s <server_ip>\n", argv[0]);return -1;}/* 1、打开客服端的socket */iSocketClientFd = socket(AF_INET, SOCK_DGRAM, 0);// 网络类型为ipv4, 传输类型为udpif(iSocketClientFd == -1){printf("socket error!\n");return -1;}/* 设置要链接的服务器端的基本信息 */tSocketServerAddr.sin_family      = AF_INET;// 网络类型为ipv4tSocketServerAddr.sin_port        = htons(SOCKET_PORT);// 服务器端的网络端口iRet = inet_aton(argv[1], &tSocketServerAddr.sin_addr);// 要连接的客服端的ip地址if(iRet == 0){printf("server ip is not valid!\n");return -1;}memset(tSocketServerAddr.sin_zero, 0, 8);iSockAddrLen = sizeof(struct sockaddr);printf("Input a message to %s: \n", argv[1]);while(1){if(fgets(ucSendBuf, ARRAY_LENGTH, stdin))// 接收用户端的输入{/* 2、强用户端的输入发送给服务器端 */iSendLen = sendto(iSocketClientFd, ucSendBuf, strlen(ucSendBuf), 0,                      (const struct sockaddr *)&tSocketServerAddr, iSockAddrLen);if(iSendLen <= 0){printf("sendto error!\n");close(iSocketClientFd);return -1;}}}close(iSocketClientFd);return 0;}

三、测试
将上面两种方式实现的客服端都和服务器进行通信测试。服务器端和客服端可以在同一台电脑上也可以在不同的电脑上(必须在同一局域网当中),本文是在同一台电脑上对客服端和服务器端进行测试,测试结果如下:

客服端一:



客服端二:



服务器端:



从上面结果可以看出,服务器和两个客服端都通信成功。


0 0