http://blog.chinaunix.net/uid-23193900-id-3199173.html
https://www.cnblogs.com/my_life/articles/4935240.html
https://blog.csdn.net/dog250/article/details/5303572
https://blog.csdn.net/dog250/article/details/6896949
无连接的socket的客户端和服务端以及面向连接socket的服务端通过调用bind函数来配置本地信息。使用bind函数时,通过将my_addr.sin_port置为0,函数会自动为你选择一个未占用的端口来使用。
Bind()函数在成功被调用时返回0;出现错误时返回"-1"并将errno置为相应的错误号。需要注意的是,在调用bind函数时一般不要将端口号置为小于1024的值,因为1到1024是保留端口号,你可以选择大于1024中的任何一个没有被占用的端口号。
有连接的socket客户端通过调用Connect函数在socket数据结构中保存本地和远端信息,无须调用bind(),因为这种情况下只需知道目的机器的IP地址,
而客户通过哪个端口与服务器建立连接并不需要关心,socket执行体为你的程序自动选择一个未被占用的端口,并通知你的程序数据什么时候打开端口。(当
然也有特殊情况,linux系统中rlogin命令应当调用bind函数绑定一个未用的保留端口号,还有当客户端需要用指定的网络设备接口和端口号进行通
信等等)
1.需要在建连前就知道端口的话,需要 bind
2.需要通过指定的端口来通讯的话,需要 bind
具体到上面那两个程序,本来用的是TCP,客户端就不用绑定端口了,绑定之后只能运行一个client的程序属于自己人为设定的障碍,而从服务器那边得到的客户机连接端口号(是系统自动分配的)与这边客户机绑定的端口号根本是不相关的,所以客户端绑定也就失去了意义。
socklen_t len; struct sockaddr_in local_addr; sockfd = socket(AF_INET, SOCK_DGRAM, 0); memset(&local_addr, 0 , sizeof(local_addr)); local_addr.sin_family = AF_INET; local_addr.sin_port = htons(0); local_addr.sin_addr.s_addr = htonl(INADDR_ANY); bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr)); getsockname(sockfd, (struct sockaddr*)&local_addr, &len);
===============
sendto(fd, buf, size, addr) :addr 远端地址,入参
recvfrom(fd, buf, size, addr) :addr 远端地址,出参
UDP connect 并没有真正建立一个连接,即没有3次握手过程,只是维护了一种状态,绑定了远程地址,因此在调用sendto 时也可以不指定远程地址了,如 sendto(sock, sendbuf, strlen(sendbuf), 0, NULL, 0);
甚至也可以使用send 函数 send(sock, sendbuf, strlen(sendbuf), 0);
假设现在客户端有多个ip地址,由connect 或 sendto 函数提供的远程地址的参数,系统会选择一个合适的出口,比如远程ip 是192.168.2.10, 而客户端现在的ip 有 192.168.1.32 和 192.168.2.75 那么会自动选择192.168.2.75 这个ip 出去。
=====================
https://blog.csdn.net/qq_29344757/article/details/71616748
1. udp客户端使用connect()函数
udp客户端建立了socket后可以直接调用sendto()函数向服务器发送数据,但是需要在sendto()函数的参数中指定目的地址/端口,但是可以调用connect()函数先指明目的地址/端口,然后就可以使用send()函数向目的地址发送数据了,因为此时套接字已经包含目的地址/端口,也就是send()函数已经知道包含目的地址/端口。
//用sendto()函数发送数据的udp客户端程序 int main(int argc, char *argv[]) { int sd; struct sockaddr_in svr_addr; int ret; socklen_t addrlen = sizeof(struct sockaddr_in); char buf[BUFSZ] = {}; if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket"); exit(EXIT_FAILURE); } //sendto()函数需要指定目的端口/地址 svr_addr.sin_family = AF_INET; svr_addr.sin_port = htons(PORT); svr_addr.sin_addr.s_addr = inet_addr("192.168.1.166"); while (1) { memset(buf, 0, BUFSZ); printf("ple input: "); fgets(buf, BUFSZ, stdin); sendto(sd, buf, BUFSZ, 0, (struct sockaddr* )&svr_addr, addrlen); ret = recvfrom(sd, buf, BUFSZ, 0, (struct sockaddr* )&svr_addr, &addrlen); printf("client: IPAddr = %s, Port = %d, buf = %s\n", inet_ntoa(svr_addr.sin_addr), ntohs(svr_addr.sin_port), buf); } close(sd); return 0; }
send()函数发送数据的udp客户端程序:
//用send()函数发送数据的udp客户端程序 int main(int argc, char *argv[]) { int sd; struct sockaddr_in svr_addr; int ret; socklen_t addrlen = sizeof(struct sockaddr_in); char buf[BUFSZ] = {}; if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket"); exit(EXIT_FAILURE); } //先调用connect()函数,为套接字指定目的地址/端口 svr_addr.sin_family = AF_INET; svr_addr.sin_port = htons(PORT); svr_addr.sin_addr.s_addr = inet_addr("192.168.1.166"); connect(sd, (struct sockaddr* )&svr_addr, addrlen); while (1) { memset(buf, 0, BUFSZ); printf("ple input: "); fgets(buf, BUFSZ, stdin); //sendto(sd, buf, BUFSZ, 0, (struct sockaddr* )&svr_addr, addrlen); send(sd, buf, BUFSZ, 0); ret = recvfrom(sd, buf, BUFSZ, 0, (struct sockaddr* )&svr_addr, &addrlen); printf("client: IPAddr = %s, Port = %d, buf = %s\n", inet_ntoa(svr_addr.sin_addr), ntohs(svr_addr.sin_port), buf); } close(sd); return 0; }
2. udp客户端程序使用bind()函数
//为客户端绑定端口和地址信息 int main(int argc, char *argv[]) { int sd; struct sockaddr_in svr_addr, cli_addr; int ret; socklen_t addrlen = sizeof(struct sockaddr_in); char buf[BUFSZ] = {}; if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket"); exit(EXIT_FAILURE); } //绑定地址信息 cli_addr.sin_family = AF_INET; cli_addr.sin_port = htons(9693); cli_addr.sin_addr.s_addr = 0; if ((ret = bind(sd, (struct sockaddr* )&cli_addr, addrlen)) < 0) { perror("bind"); exit(EXIT_FAILURE); } svr_addr.sin_family = AF_INET; svr_addr.sin_port = htons(PORT); svr_addr.sin_addr.s_addr = inet_addr("192.168.1.166"); while (1) { memset(buf, 0, BUFSZ); printf("ple input: "); fgets(buf, BUFSZ, stdin); sendto(sd, buf, BUFSZ, 0, (struct sockaddr* )&svr_addr, addrlen); ret = recvfrom(sd, buf, BUFSZ, 0, (struct sockaddr* )&svr_addr, &addrlen); printf("client: IPAddr = %s, Port = %d, buf = %s\n", inet_ntoa(svr_addr.sin_addr), ntohs(svr_addr.sin_port), buf); } close(sd); return 0; }
3. udp服务器程序使用connect()函数
如上所述,connect()函数可以用来指明套接字的目的地址/端口号,那么若udp服务器可以使用connect,将导致服务器只接受这特定一个主机的请求。
---------------------
http://blog.chinaunix.net/uid-20401941-id-3178235.html
在水木上看到一个关于在客户端调用bind的讨论,
点击(此处)折叠或打开
- #include <sys/socket.h>
- #include <unistd.h>
- #include <string.h>
- #include <stdio.h>
- #include <arpa/inet.h>
- #include <stdlib.h>
- #define MAXLINE 80
- #define SERV_PORT 8888
- struct sockaddr_in servaddr;
- void do_cli(FILE *fp,int sockfd,struct sockaddr *pservaddr,socklen_t servlen)
- {
- int n;
- char sendline[MAXLINE],recvline[MAXLINE + 1];
- #ifdef UDP_CONNECT
- /* connect to server */
- if(connect(sockfd,(struct sockaddr *)pservaddr,servlen) == -1)
- {
- perror("connect error");
- exit(1);
- }
- #endif
- while(fgets(sendline,MAXLINE,fp) != NULL)
- {
- #ifdef UDP_CONNECT
- /* read a line and send to server */
- write(sockfd,sendline,strlen(sendline));
- #else
- sendto(sockfd, sendline, strlen(sendline), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
- #endif
- printf("write over\n");
- /* receive data from server */
- n = read(sockfd,recvline,MAXLINE);
- if(n == -1)
- {
- perror("read error");
- exit(1);
- }
- recvline[n] = 0; /* terminate string */
- fputs(recvline,stdout);
- }
- }
- int main(int argc,char **argv)
- {
- int sockfd;
- /* check args */
- if(argc != 2)
- {
- printf("usage: udpclient serverip\n");
- exit(1);
- }
- /* init servaddr */
- bzero(&servaddr,sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_port = htons(SERV_PORT);
- if(inet_pton(AF_INET,argv[1],&servaddr.sin_addr) <= 0)
- {
- printf("[%s] is not a valid IPaddress\n",argv[1]);
- exit(1);
- }
- sockfd = socket(AF_INET,SOCK_DGRAM,0);
- do_cli(stdin,sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
- return 0;
- }