您的位置:首页 > 其它

固定端口的socket通信

2015-11-14 00:02 330 查看
在多台机器互联的场景下,可能会出现无法通信的情形,可能原因有:代码出错,地址出错,防火墙。对于防火墙的命令,后面会提及。

对于前两种错误debug就可以解决。如果这两种情况都不是,那么极有可能是防火墙的问题,我们可以通过wireshark来抓包进行分析。在wireshark抓包中,我们看到当fedora作为服务器接受到客户端的请求之后,给主机发回的信息会被host administratively prohibited。由此判断出是防火墙的问题。

对于防火墙拒绝了数据包,我们可以用两种方式处理:

1. 直接关闭防火墙,不推荐,但我们使用的是这个。

2. 通过在防火墙上添加允许通过的端口号来打开我们需要的端口。

所以,绑定端口的UDP通信十分必要。首先,我们需要知道的是

客户端所初始化的struct sockaddr_in 的端口、地址都是所发送到的服务器端的端口、地址。而服务器端所初始化的struct sockaddr_in 是指其本身监听的端口和地址。其次,如果想要固定端口号,对sendto()函数的参数有所要求,第一个参数为我们绑定了客户端地址、端口号的套接字,第五个参数则为赋值了服务器的端口号、地址的sockaddr_in。这里的一个小技巧是声明一个strcut sockaddr_in 变量,在对其初始化客户端端口号、地址并绑定过套接字后,再对此变量重新赋值为服务器的客户端、地址。服务器端会根据收到的数据包中的客户端端口号、地址回复。

下面给出固定端口号的客户端代码,因为服务端会根据客户端的端口号来回复。

这里我们只给出main函数,因为另外两个函数依然可用上一篇

linux下socket通信代码的开发及总结—UDP的内容

/article/11259808.html

int main(int argc, char** argv){

/* check args */
if (argc !=2){
printf("Usage: udp_request IP\n");
exit(1);
}

//创建两个线程
pthread_t threadrecv,threadsend;
void *retval;

int port = 4600;
int udp_descriptor;

struct sockaddr_in udpaddr;

//固定客户端端口号为4600
bzero(&udpaddr,sizeof(udpaddr));
udpaddr.sin_family=AF_INET;
udpaddr.sin_port=htons(port);
udpaddr.sin_addr.s_addr= inet_addr("192.168.1.3");//这里的地址应该为你客户端所用的ip地址

int udp_descriptor = socket(AF_INET,SOCK_DGRAM,0);

if(udp_descriptor == -1){
printf("Create Socket Failed!\n");
exit(1);
}
if(bind(udp_descriptor,(struct sockaddr*)&udpaddr,sizeof(udpaddr)) == -1 ){
printf("Server Bind Failed!\n");
exit(1);
}

udpaddr.sin_port=htons(port);
inet_pton(AF_INET, argv[1], &udpaddr.sin_addr);

struct argu_send args;
args.adres =&udpaddr;
args.sock = udp_descriptor;

/*while(1)
{
send_msg(&args);
get_msg(server_descriptor);
sleep(3);
}*/
pthread_create(&threadsend,NULL,(void*)(&send_msg),&args);

pthread_create(&threadrecv,NULL,(void*)(&get_msg),&udp_descriptor);

pthread_join(threadrecv,&retval);
pthread_join(threadsend,&retval);

return 0;
}


值得一提的是,代码中用了多线程来实现,也可以不用线程,直接用循环来实现。代码中只需把注释掉的部分取消注释,并且去掉线程的部分即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: