1、采用TCP通信时,客户端不需要bind()他自己的IP和端口号,而服务器必须要bind()自己本机的IP和端口号;
2、若采用UDP通信时(这里是有客户端和服务器之分才这么说的,若是指定特定端口的UDP对等通信则不一样了),客户端也可以不需要bind()他自己的IP和端口号,而服务器需要bind自己IP地址和端口号;
原因:
1、
因为服务器是时时在监听有没有客户端的连接,如果服务器不绑定IP和端口的话,客户端上线的时候怎么连到服务器呢,所以服务器要绑定IP和端口,而客户端就不需要了,客户端上线是主动向服务器发出请求的,因为服务器已经绑定了IP和端口,所以客户端上线的就向这个IP和端口发出请求,这时因为客户开始发数据了(发上线请求),系统就给客户端分配一个随机端口,这个端口和客户端的IP会随着上线请求一起发给服务器,服务收到上线请求后就可以从中获起发此请求的客户的IP和端口,接下来服务器就可以利用获起的IP和端口给客户端回应消息了。
2、采用UDP通信
1)若有客户端和服务器之分的程序,创建sock后即可在该socket上用recvfrom/sendto方法发送接受数据了,因为客户端只需要用sendto发送数据到指定的地址,当然若是bind了,程序也没什么问题,区别就是系统用默认自动bind()指定你自己的socket参数地址(特别是在指定特定端口的UDP对等通信)只是这种情况没有这样用的。
那UDP服务器是怎么知道客户端的IP地址和UDP端口?
一般来说有两种方式:
一种是客户端发消息显式地告诉服务器IP地址和端口,消息内容就包括IP地址和UDP端口。
另外一种就是隐式的,服务器从收到的包的头部中得到包的源IP地址和端口。
2)若是没有客户端和服务器之分的程序,即自己指定特定端口的UDP对等通信,则客户端和服务器都需要bind()IP地址和端口了。
通常udp服务端根本不需要知道客户端的socket,它直接建立一个socket用于发送即可,udp通信的关键只在于IP和端口。
多个客户端如果需要点到点分发,必须给服务端socket循环设置每个客户端的IP并发出,但更常用的是广播分发,服务端socket设定一个X.X.X.255的广播地址并始终向它发送,每个客户端建立的socket只需要绑定这个广播地址便可以收到。
客户端用不用bind 的区别
Bind()函数在成功被调用时返回0;出现错误时返回"-1"并将errno置为相应的错误号。需要注意的是,在调用bind函数时一般不要将端口号置为小于1024的值,因为1到1024是保留端口号,你可以选择大于1024中的任何一个没有被占用的端口号。
有连接的socket客户端通过调用Connect函数在socket数据结构中保存本地和远端信息,无须调用bind(),因为这种情况下只需知道目的机器的IP地址,而客户通过哪个端口与服务器建立连接并不需要关心,socket执行体为你的程序自动选择一个未被占用的端口,并通知你的程序数据什么时候打开端口。(当然也有特殊情况,linux系统中rlogin命令应当调用bind函数绑定一个未用的保留端口号,还有当客户端需要用指定的网络设备接口和端口号进行通信等等)
1.需要在建连前就知道端口的话,需要 bind
2.需要通过指定的端口来通讯的话,需要 bind
具体到上面那两个程序,本来用的是TCP,客户端就不用绑定端口了,绑定之后只能运行一个client 的程序,是属于自己程序中人为设定的障碍,而从服务器那边得到的客户机连接端口号(是系统自动分配的)与这边客户机绑定的端口号根本是不相关的,所以客户 绑定也就失去了意义。
=======================================================
客户端调用bind 的作用及UDP客户端调用connect 的问题
在水木上看到一个关于在客户端调用bind的讨论,
-
1.
-
-
2.
-
-
3.
-
-
4.
-
-
5.
-
-
6.
-
-
7.
-
-
8.
-
-
9.
-
-
10.
-
-
11. struct sockaddr_in servaddr;
-
-
12.
-
-
13. void do_cli(FILE *fp,int sockfd,struct sockaddr *pservaddr,socklen_t servlen)
-
-
14.{
-
-
15. int n;
-
-
16. char sendline[MAXLINE],recvline[MAXLINE + 1];
-
-
17.
-
-
18.
-
-
19. /* connect to server */
-
-
20. if(connect(sockfd,(struct sockaddr *)pservaddr,servlen) == -1)
-
-
21. {
-
-
22. perror( "connect error");
-
-
23. exit( 1);
-
-
24. }
-
-
25.
-
-
26.
-
-
27. while(fgets(sendline,MAXLINE,fp) != NULL)
-
-
28. {
-
-
29.
-
-
30. /* read a line and send to server */
-
-
31. write(sockfd,sendline, strlen(sendline));
-
-
32.
-
-
33. sendto(sockfd, sendline, strlen(sendline), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
-
-
34.
-
-
35.
-
-
36. printf( "write over\n");
-
-
37. /* receive data from server */
-
-
38. n = read(sockfd,recvline,MAXLINE);
-
-
39. if(n == -1)
-
-
40. {
-
-
41.
-
-
42. perror( "read error");
-
-
43. exit( 1);
-
-
44. }
-
-
45. recvline[n] = 0; /* terminate string */
-
-
46. fputs(recvline, stdout);
-
-
47. }
-
-
48.}
-
-
49.
-
-
50. int main(int argc,char **argv)
-
-
51.{
-
-
52. int sockfd;
-
-
53.
-
-
54. /* check args */
-
-
55. if(argc != 2)
-
-
56. {
-
-
57. printf( "usage: udpclient serverip\n");
-
-
58. exit( 1);
-
-
59. }
-
-
60.
-
-
61. /* init servaddr */
-
-
62. bzero(&servaddr, sizeof(servaddr));
-
-
63. servaddr.sin_family = AF_INET;
-
-
64. servaddr.sin_port = htons(SERV_PORT);
-
-
65. if(inet_pton(AF_INET,argv[ 1],&servaddr.sin_addr) <= 0)
-
-
66. {
-
-
67. printf( "[%s] is not a valid IPaddress\n",argv[ 1]);
-
-
68. exit( 1);
-
-
69. }
-
-
70. sockfd = socket(AF_INET,SOCK_DGRAM, 0);
-
-
71. do_cli( stdin,sockfd,(struct sockaddr *)&servaddr, sizeof(servaddr));
-
-
72. return 0;
-
-
73.}