本文参考了以下博客内容:
基于Linux下的TCP编程,基于Linux下的UDP编程,udp socket编程中的connect()。
对于通信,首先需要对方的地址,这里对方的地址就是IP:port组成的套接字。1 TCP
tcp是有连接的,所以它会在建立连接后,双方都知晓了对方的地址,可以进行通信。顺序为一端bind(),另一端
connect()。
bind()函数即为其确定了一个套接字的地址,因此通信的一方就确定了。另一方connect(),为了表述
方便,不妨称其为B ,若此时B还未确定套接字地址,则
connect()将为其
透明的分配一个套接字地址用以通信。
A方,即上述bind()方,accept()到这个连接后,同时为accept()的(struct sockaddr_in)类型的参数赋
了值。此
时,双方均知晓对方的
地址,就可以通信了。
2 UDP
udp是无连接的,因此和上述有所不同,因为我们不能通过连接来知晓对方的地址。有以下两种方式来完成,同样
假设为A,B两方。
(1)
A方:bind(),recvfrom(),sendto();
B方:sendto(),recvfrom();
无论怎样,要想通信,必须至少先确定一方的地址,因此bind()函数是必须的。此时A还不知道另一方的套接字,
所以调用recvfrom()来获取对方地址,当然,
在B调用sendto()
前,A将阻塞。
顺序就是A方recvfrom(),B方
sendto(),B方recvfrom(),A在sendto(),recvfrom()......
这其中,每次recvfrom()都是一次地址更新的过程,如果两方不停传输很多消息,显然这个地址更新很没必要。
(2)
另一种就是不使用recvfrom()函数了,这样就不会更新地址了,但是发送消息的时候我们需要地址,怎么办?
此时使用connect函数。此时,像tcp中一样,B方connect后,就可以使用recv(),send()函数了,这样B就可以
不用一直更新地址了。但是A依然需要不停的
recvfrom(),sendto()
(我没那能力看源码,做实验得到的)。所以
我们容易想到让A方也connect(),但是connect()到哪个地址呢?这就需要知晓对方的地址,
需要对方确定自己
的地址,也即让B也
bind()一个地址,确定自己的套接字,这样就变成,如下
A:bind(),connect(),send(),recv().......
B: bind(),connect(),recv(),send()............
通信方A:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define PORT 1111 /*使用的port*/
int main(){
int sockfd,len;
struct sockaddr_in addr,clientaddr;
char buffer[256];
/*建立socket*/
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0){
perror ("socket");
exit(1);
}
/*填写sockaddr_in 结构*/
bzero ( &addr, sizeof(addr) );
addr.sin_family=AF_INET;
addr.sin_port=htons(PORT);
addr.sin_addr.s_addr=htonl(INADDR_ANY) ;
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr))<0){
perror("connect");
exit(1);
}
memset(&clientaddr,0,sizeof(struct sockaddr_in));
clientaddr.sin_family = AF_INET;
clientaddr.sin_port = htons(5555);
clientaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sockfd,(struct sockaddr*)&clientaddr,sizeof(struct sockaddr_in));
while(1){
bzero(buffer,sizeof(buffer));
len = recv(sockfd,buffer,sizeof(buffer), 0);// , (struct sockaddr *)&addr ,&addr_len);
/*显示client端的网络地址*/
printf("receive from %s:%d,%s\n" , inet_ntoa( addr.sin_addr),ntohs(addr.sin_port),buffer);
/*将字串返回给client端*/
send(sockfd,buffer,len,0);//,(struct sockaddr *)&addr,addr_len);
printf("send complete\n");
}
}
通信方B;
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
using namespace std;
int main()
{
int sock = socket(AF_INET,SOCK_DGRAM,0);
if(sock == -1)
cout << "create socket error" << endl;
struct sockaddr_in serveraddr,clientaddr;
memset(&serveraddr,0,sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(1111);
serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(&clientaddr,0,sizeof(struct sockaddr_in));
clientaddr.sin_family = AF_INET;
clientaddr.sin_port = htons(5555);
clientaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
bind(sock,(struct sockaddr*)&clientaddr,sizeof(struct sockaddr_in));
int rc = connect(sock,(struct sockaddr*)&serveraddr,sizeof(struct sockaddr_in));
if(rc == -1)
cout << "connect error" << endl;
char send_buff[10];
send_buff[0] = '1';
send_buff[1] = 0;
//socklen_t len = sizeof(struct sockaddr_in);
send(sock,send_buff,10,0);//,(struct sockaddr*)&serveraddr,len);
recv(sock,send_buff,10,0);//,(struct sockaddr*)&serveraddr,&len);
cout << "complete" << endl;
close(sock);
}