linux下使用udpsocket时遇到的问题
关于数据报socket的使用,很多博客都有,由于事先已知客户端的ip字串,不想服务端使用通过recvfrom时保存下来的struct sockaddr_in*类型ip,想通过之前ip字串来让服务器给客户端发送数据,发现出现了问题,仔细研究后发现是发送数据给客户端时,使用了之前的服务器绑定的端口,这是不对的,客户端的端口是系统随机分配的,必须要使用之前获取客户端地址时的端口,因此必须保存该端口,其次也可以固定一个客户端端口,这样客户端需要初始化ip,同时绑定ip和端口。
具体代码如下:
客户端:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#define SERVER_PORT 8000
#define CLIENT_PORT 8001
int main()
{
int sock_fd;
int send_num;
int recv_num;
int dest_len;
char send_buf[1024] = "hello server";
char recv_buf[1024];
struct sockaddr_in addr_serv;
struct sockaddr_in addr_client;
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (sock_fd < 0)
{
printf("create socket failed\n");
return -1;
}
//初始化本机地址
memset(&addr_client, 0, sizeof(addr_client));
addr_client.sin_family = AF_INET;
addr_client.sin_addr.s_addr = htonl(INADDR_ANY); //IP地址,需要进行网络序转换,INADDR_ANY:本地地址
addr_client.sin_port = htons(CLIENT_PORT);
if (bind(sock_fd, (struct sockaddr*)&addr_client, sizeof(addr_client)) < 0)
{
printf("client bind failed\n");
return -1;
}
printf("client bind sucessful\n");
//初始化服务端地址
addr_serv.sin_family = AF_INET;
addr_serv.sin_addr.s_addr = inet_addr("192.168.16.130");
addr_serv.sin_port = htons(SERVER_PORT);
dest_len = sizeof(struct sockaddr_in);
printf("begin send:\n");
send_num = sendto(sock_fd, send_buf, sizeof(send_buf), 0, (struct sockaddr*)&addr_serv, dest_len);
if (send_num < 0)
{
printf("send to message fialed\n");
return -1;
}
else
{
printf("send sucessful:%s\n",send_buf);
}
printf("send_num:%d\n", send_num);
printf("client sock_id:%d\n", sock_fd);
recv_num = recvfrom(sock_fd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr*)&addr_serv, &dest_len);
printf("recvbuf:%s\n", recv_buf);
if (recv_num < 0)
{
perror("recv_from");
}
else
{
printf("recv sucessful\n");
}
recv_buf[recv_num]='\0';
printf("the receive:%s\n",recv_buf);
close(sock_fd);
return 0;
}
服务端代码:
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <netdb.h>
#include <stdarg.h>
#include <string.h>
#define SERVER_PORT 8000
#define CLIENT_PORT 8001
#define BUFF_LEN 1024
using namespace std;
int main(int argc, char* argv[])
{
int server_fd, ret;
struct sockaddr_in ser_addr;
char buf[BUFF_LEN]; //接收缓冲区,1024字节
struct sockaddr_in clent_addr;
socklen_t len;
int send_len;
int count;
char buffer[BUFF_LEN] = "fuck"; //接收缓冲区,1024字节
server_fd = socket(AF_INET, SOCK_DGRAM, 0); //AF_INET:IPV4;SOCK_DGRAM:UDP
if (server_fd < 0) {
printf("create socket fail!\n");
return -1;
}
/* udfServer初始化 */
memset(&ser_addr, 0, sizeof(ser_addr));
ser_addr.sin_family = AF_INET;
ser_addr.sin_addr.s_addr = htonl(INADDR_ANY); //IP地址,需要进行网络序转换,INADDR_ANY:本地地址
ser_addr.sin_port = htons(SERVER_PORT); //端口号,需要网络序转换
ret = bind(server_fd, (struct sockaddr*) &ser_addr, sizeof(ser_addr));
if (ret < 0) {
printf("socket bind fail!\n");
return -1;
}
memset(buf, 0, BUFF_LEN);
len = sizeof(clent_addr);
ret = recvfrom(server_fd, buf, BUFF_LEN, 0, (struct sockaddr*) &clent_addr,
&len); //recvfrom是拥塞函数,没有数据就一直拥塞
if (ret < 0) {
printf("recieve data fail!\n");
}
printf("client:%s\n", buf); //打印client发过来的信息
printf("ClientIp is %4x\n", ntohl(clent_addr.sin_addr.s_addr));
printf("%s\n", inet_ntoa(clent_addr.sin_addr));
struct in_addr addr;
memset(&addr, 0, sizeof(struct in_addr));
string ip = "192.168.16.1";
ret = inet_aton(ip.c_str(), &addr);
if (0 > ret) {
cout << "stringip to uint32ip is failed" << endl;
}
struct sockaddr_in sockClient;
memset(&sockClient, 0, sizeof(sockaddr_in));
sockClient.sin_family = AF_INET;
sockClient.sin_addr.s_addr = htonl(ntohl(addr.s_addr));
sockClient.sin_port = htons(CLIENT_PORT);
printf("%s\n", inet_ntoa(sockClient.sin_addr));
while (1)
{
send_len = sendto(server_fd, buffer, BUFF_LEN, 0,
(struct sockaddr*) &sockClient, sizeof(sockClient));
if (send_len < 0)
{
cout << "send_len:" << send_len << endl;
}
cout << "send_len:" << send_len << endl;
cout << "buffer:" << buffer << endl;
}
close(server_fd);
return 0;
}
测试结果如下: