linux网络编程(如何编写一个UDP通信程序)
来源:互联网 发布:社交网络 mp4 编辑:程序博客网 时间:2024/05/21 20:30
UDP数据通讯原理
UDP数据通讯分服务端(软件)和客户端端:
服务端(软件)(服务器)先运行,服务端,不需要事先知道客户端IP和port
客户端(软件)(客户端机器)后运行,一定是客户端先给服务端发包,客户端一定先知道服务端的IP和port
UDP通信实现
1. 头文件
#include <sys/types.h>
#include <sys/socket.h>
2. 数据结构
// Internet协议地址结构
struct sockaddr{
// 地址的通信领域
unsigned short int sa_family;
// ip(4B) 和 port(2B)
char sa_data[14];
};
// 通用数据结构
struct sockaddr_in {
unsigned short int sin_family;
unsigned short int sin_port; // port
struct in_addr sin_addr; // ip地址
// 填充0 (8B)
unsigned char sin_zero[sizeof (struct sockaddr) -
(sizeof (unsigned short int)) -
sizeof (unsigned short int) -
sizeof (struct in_addr)];
};
(1) 创建套接字(创建并且打开套接字)
/*
* @param[in] domain通信领域
* @li AF_UNIX, AF_LOCAL unix域套接字通信(本机进程间)
* @li AF_INET IPv4协议通信
* @li AF_INET6 IPv6协议通信
* @param[in] type套接字类型
* @li SOCK_STREAM流式套接字
* @li SOCK_DGRAM报文套接字
* @li SOCK_RAW 网络层的协议访问
* @param[in] protocol协议标识
* @li 0使用默认协议
*
* @return 文件描述符
* @li -1创建失败(错误码见errno)
*/
int socket(int domain, int type, int protocol);
(2) 绑定ip地址和port(到socket(一定一个进程创建))
/*
* @param[in] sockfdsocket
* @param[in] addr绑定地址(ip地址和port)
* @param[in] addrlenaddr的字节数
* @return @li 0绑定成功
* @li -1创建失败(错误码见errno)
*/
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
(3) 接收数据包
/*
* @param[in] sockfdsocket
* @param[out] buf 接收数据包的buf
* @param[in] lenbuf的字节数
* @param[in] flags0
* @param[out] src_addr源地址(IP和Port)
* @NULL不接收源地址,此时addrlen也必须为NULL
* @param[in | out] addrlen(输入)src_addr缓冲区字节数
* addrlen(输出) 实际地址大小
* @return @li >= 0实际接收的字节数
* @li -1创建失败(错误码见errno)
*/
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
(4) 发送数据包
/*
* @param[in] sockfdsocket
* @param[out] buf 发送数据包的buf
* @param[in] len发送数据的字节数
* @param[in] flags0
* @param[out] dest_addr目标地址(IP和Port)
* @param[in] addrlendest_addr字节数
* @return @li >= 0实际发送的字节数
* @li -1发送失败(错误码见errno)
*/
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
(5) 关闭socket
int close(int sockfd);
客户端流程
(1) 创建套接字(创建并且打开套接字)
(2) 发送数据包
(3) 接收数据包
(4) 关闭socket
/*
* 实现目标:
* udp客户端
*
* 实现步骤:
* 1. socket
* 2. 获取用户输入
* 3. sendto用户输入的内容
* 4. recvfrom服务器发送过来的内容,并显示
* 5. close
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <strings.h>
// net
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// ./client 192.168.0.249 8888
int main(int argc, const char *argv[])
{
int ret = 0;
int sockfd;
char packet[1024];
struct sockaddr_in server_addr;
struct sockaddr_in peer_addr;
socklen_t addrlen = sizeof(peer_addr);
if (argc < 3){
fprintf(stderr, "Usage: %s <server ip> <server port>\n", argv[0]);
exit(EXIT_FAILURE);
}
// 1. socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == sockfd){
perror("Fail to socket.");
exit(EXIT_FAILURE);
}
// 填充地址结构
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[2]));
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
while (1){
// 2. 获取用户输入
putchar('>');
fgets(packet, sizeof(packet), stdin);
packet[strlen(packet) - 1] = '\0';
// 3. sendto用户输入的内容
ret = sendto(sockfd, packet, strlen(packet), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (-1 == ret){
perror("Fail to sendto");
break;
}
// 4. recvfrom服务器发送过来的内容,并显示
ret = recvfrom(sockfd, packet, sizeof(packet), 0, (struct sockaddr *)&peer_addr, &addrlen);
if (-1 == ret){
perror("Fail to recvfrom.");
break;
}
packet[ret] = '\0';
printf("recv : %s\n", packet);
if (strcmp(packet, "bye") == 0) break;
}
// 5. close
close(sockfd);
return 0;
}
/*
* 实现目标:
* udp服务端
*
* 实现步骤:
* 1. socket
* 2. bind
* 3. recvfrom客户发送的内容
* 4. sendto相同的内容客户端
* 5. close
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
// bzero
#include <strings.h>
// net
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// ./server 192.168.0.249 8888
int main(int argc, const char *argv[])
{
int ret = 0;
int sockfd;
struct sockaddr_in server_addr;
struct sockaddr_in peer_addr;
socklen_t addr_len = sizeof(peer_addr);
char packet[1024];
if (argc < 3){
fprintf(stderr, "Usage: %s <ip> <port>\n", argv[0]);
exit(EXIT_FAILURE);
}
// 1. socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == sockfd){
perror("Fail to socket.");
exit(EXIT_FAILURE);
}
// 2. bind
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[2]));
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
if (-1 == ret){
perror("Fail to bind.");
exit(EXIT_FAILURE);
}
while (1) {
// 3. recvfrom客户发送的内容
ret = recvfrom(sockfd, packet, sizeof(packet), 0, (struct sockaddr *)&peer_addr, &addr_len);
if (-1 == ret){
perror("Fail to recvfrom.");
break;
}
packet[ret] = '\0';
printf("----------------------------------------\n");
printf("ip : %s\n", inet_ntoa(peer_addr.sin_addr));
printf("port : %d\n", ntohs(peer_addr.sin_port));
printf("recv : %s\n", packet);
printf("----------------------------------------\n");
// 4. sendto相同的内容客户端
ret = sendto(sockfd, packet, ret, 0, (struct sockaddr *)&peer_addr, sizeof(struct sockaddr));
if (-1 == ret){
perror("Fail to sendto.");
break;
}
if (strcmp(packet, "bye") == 0) break;
}
// 5. close
close(sockfd);
return 0;
}
UDP数据通讯分服务端(软件)和客户端端:
服务端(软件)(服务器)先运行,服务端,不需要事先知道客户端IP和port
客户端(软件)(客户端机器)后运行,一定是客户端先给服务端发包,客户端一定先知道服务端的IP和port
UDP通信实现
1. 头文件
#include <sys/types.h>
#include <sys/socket.h>
2. 数据结构
// Internet协议地址结构
struct sockaddr{
// 地址的通信领域
unsigned short int sa_family;
// ip(4B) 和 port(2B)
char sa_data[14];
};
// 通用数据结构
struct sockaddr_in {
unsigned short int sin_family;
unsigned short int sin_port; // port
struct in_addr sin_addr; // ip地址
// 填充0 (8B)
unsigned char sin_zero[sizeof (struct sockaddr) -
(sizeof (unsigned short int)) -
sizeof (unsigned short int) -
sizeof (struct in_addr)];
};
3. 函数
服务端流程(1) 创建套接字(创建并且打开套接字)
/*
* @param[in] domain通信领域
* @li AF_UNIX, AF_LOCAL unix域套接字通信(本机进程间)
* @li AF_INET IPv4协议通信
* @li AF_INET6 IPv6协议通信
* @param[in] type套接字类型
* @li SOCK_STREAM流式套接字
* @li SOCK_DGRAM报文套接字
* @li SOCK_RAW 网络层的协议访问
* @param[in] protocol协议标识
* @li 0使用默认协议
*
* @return 文件描述符
* @li -1创建失败(错误码见errno)
*/
int socket(int domain, int type, int protocol);
(2) 绑定ip地址和port(到socket(一定一个进程创建))
/*
* @param[in] sockfdsocket
* @param[in] addr绑定地址(ip地址和port)
* @param[in] addrlenaddr的字节数
* @return @li 0绑定成功
* @li -1创建失败(错误码见errno)
*/
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
(3) 接收数据包
/*
* @param[in] sockfdsocket
* @param[out] buf 接收数据包的buf
* @param[in] lenbuf的字节数
* @param[in] flags0
* @param[out] src_addr源地址(IP和Port)
* @NULL不接收源地址,此时addrlen也必须为NULL
* @param[in | out] addrlen(输入)src_addr缓冲区字节数
* addrlen(输出) 实际地址大小
* @return @li >= 0实际接收的字节数
* @li -1创建失败(错误码见errno)
*/
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
(4) 发送数据包
/*
* @param[in] sockfdsocket
* @param[out] buf 发送数据包的buf
* @param[in] len发送数据的字节数
* @param[in] flags0
* @param[out] dest_addr目标地址(IP和Port)
* @param[in] addrlendest_addr字节数
* @return @li >= 0实际发送的字节数
* @li -1发送失败(错误码见errno)
*/
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
(5) 关闭socket
int close(int sockfd);
客户端流程
(1) 创建套接字(创建并且打开套接字)
(2) 发送数据包
(3) 接收数据包
(4) 关闭socket
/*
* 实现目标:
* udp客户端
*
* 实现步骤:
* 1. socket
* 2. 获取用户输入
* 3. sendto用户输入的内容
* 4. recvfrom服务器发送过来的内容,并显示
* 5. close
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <strings.h>
// net
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// ./client 192.168.0.249 8888
int main(int argc, const char *argv[])
{
int ret = 0;
int sockfd;
char packet[1024];
struct sockaddr_in server_addr;
struct sockaddr_in peer_addr;
socklen_t addrlen = sizeof(peer_addr);
if (argc < 3){
fprintf(stderr, "Usage: %s <server ip> <server port>\n", argv[0]);
exit(EXIT_FAILURE);
}
// 1. socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == sockfd){
perror("Fail to socket.");
exit(EXIT_FAILURE);
}
// 填充地址结构
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[2]));
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
while (1){
// 2. 获取用户输入
putchar('>');
fgets(packet, sizeof(packet), stdin);
packet[strlen(packet) - 1] = '\0';
// 3. sendto用户输入的内容
ret = sendto(sockfd, packet, strlen(packet), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (-1 == ret){
perror("Fail to sendto");
break;
}
// 4. recvfrom服务器发送过来的内容,并显示
ret = recvfrom(sockfd, packet, sizeof(packet), 0, (struct sockaddr *)&peer_addr, &addrlen);
if (-1 == ret){
perror("Fail to recvfrom.");
break;
}
packet[ret] = '\0';
printf("recv : %s\n", packet);
if (strcmp(packet, "bye") == 0) break;
}
// 5. close
close(sockfd);
return 0;
}
/*
* 实现目标:
* udp服务端
*
* 实现步骤:
* 1. socket
* 2. bind
* 3. recvfrom客户发送的内容
* 4. sendto相同的内容客户端
* 5. close
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
// bzero
#include <strings.h>
// net
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// ./server 192.168.0.249 8888
int main(int argc, const char *argv[])
{
int ret = 0;
int sockfd;
struct sockaddr_in server_addr;
struct sockaddr_in peer_addr;
socklen_t addr_len = sizeof(peer_addr);
char packet[1024];
if (argc < 3){
fprintf(stderr, "Usage: %s <ip> <port>\n", argv[0]);
exit(EXIT_FAILURE);
}
// 1. socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == sockfd){
perror("Fail to socket.");
exit(EXIT_FAILURE);
}
// 2. bind
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[2]));
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
if (-1 == ret){
perror("Fail to bind.");
exit(EXIT_FAILURE);
}
while (1) {
// 3. recvfrom客户发送的内容
ret = recvfrom(sockfd, packet, sizeof(packet), 0, (struct sockaddr *)&peer_addr, &addr_len);
if (-1 == ret){
perror("Fail to recvfrom.");
break;
}
packet[ret] = '\0';
printf("----------------------------------------\n");
printf("ip : %s\n", inet_ntoa(peer_addr.sin_addr));
printf("port : %d\n", ntohs(peer_addr.sin_port));
printf("recv : %s\n", packet);
printf("----------------------------------------\n");
// 4. sendto相同的内容客户端
ret = sendto(sockfd, packet, ret, 0, (struct sockaddr *)&peer_addr, sizeof(struct sockaddr));
if (-1 == ret){
perror("Fail to sendto.");
break;
}
if (strcmp(packet, "bye") == 0) break;
}
// 5. close
close(sockfd);
return 0;
}
0 0
- linux网络编程(如何编写一个UDP通信程序)
- Linux网络通信(二)Socket编写TCP/UDP
- Linux网络通信(二)Socket编写TCP/UDP
- Linux网络通信(二)Socket编写TCP/UDP
- 使用UDP协议编写一个网络程序
- Linux网络编程——UDP通信(文件传输)
- [Linux C编程]UDP网络通信
- 用java编写简单UDP网络通信程序
- 用java编写简单UDP网络通信程序
- 用java编写简单UDP网络通信程序
- 网络编程与多线程的应用--基于socket udp编写一个简单聊天程序
- 网络编程--UDP通信
- 网络编程-udp通信
- <网络编程培训之四> 编写一个UDP聊天室
- 网络编程编写一个聊天程序
- 网络通信UDP(Linux/Windows)
- Linux—网络通信(UDP)
- VS2010编写UDP网络通信程序的问题(借用孙鑫老师《深入VC++》书中程序)
- fibonacci数列矩阵快速幂
- linux内核的三种主要调度策略
- ROS学习 ——使用rosinstall下载源文件
- 第14周项目3-
- app被Rejected 的各种原因
- linux网络编程(如何编写一个UDP通信程序)
- LIB和DLL的区别与使用
- HDU-1048-The Hardest Problem Ever(C++ && 偶尔一水......)
- 常用命令
- linux socket 传输大文件解决方案
- Shader基础实例之动画序列帧播放
- Extension与Category
- 第一个只出现一次的字符
- Java基础 集合框架 共性方法 迭代器 ArrayList LinkedList Vector HashSet TreeSet