关于UDP网络编程最基本的控制台程序的几个问题

wuxia2118 2018-03-19 09:38:44
我是刚学网络编程的,对Socket编程最基本的程序总有很多疑问,想请教大家,下面是UDP 服务器端和客户端的程序

//服务器端
#include "iostream.h"
#include "windows.h"
#pragma comment(lib, "ws2_32.lib ")

int main(){
WSADATA wsaData;

WSAStartup(MAKEWORD(2,2), &wsaData);

cout<<"waiting message from client:"<<endl; //为什么总要等到收到客户端消息才会显示该输出的内容
SOCKET sockSer;
sockSer=socket(AF_INET, SOCK_DGRAM, 0);

sockaddr_in addrSer,addrCli;
addrSer.sin_family=AF_INET;
addrSer.sin_port=htons(5566);
//addrSer.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
addrSer.sin_addr.s_addr = INADDR_ANY;

bind(sockSer,(SOCKADDR*)&addrSer,sizeof(addrSer));

char sendbuf[256]= "\0"; //为什么该字符数组无论赋值0还是不赋值都可以,没有结束符输出时怎么知道字符串是否结束了呢
char recvbuf[256]= "\0";

int len=sizeof(SOCKADDR);
while(1){

recvfrom(sockSer,recvbuf,256,0,(SOCKADDR *)&addrCli,&len);
cout<<"客户端:>" <<recvbuf<<endl;
cout<<"服务器:>";
cin>>sendbuf;
if(strcmp(sendbuf,"bye")==0)
break;
sendto(sockSer,sendbuf,strlen(sendbuf)+1,0,(SOCKADDR *)&addrCli,len);
}

closesocket(sockSer);
WSACleanup();
return 0;
}


//客户端
#include "iostream.h"
#include "windows.h"
#pragma comment(lib, "ws2_32.lib ")

int main(){

WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);

SOCKET sockCli;
sockCli=socket(AF_INET,SOCK_DGRAM,0);

SOCKADDR_IN addrSer,addrCli;
addrSer.sin_family=AF_INET;
addrSer.sin_port=htons(5566);
addrSer.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); //这个是要连接的服务器端的IP地址吗


char sendbuf[256];
char recvbuf[256];
int len=sizeof(SOCKADDR);
while(1){
cout<<"客户端:>";
cin>>sendbuf;
if(strcmp(sendbuf,"bye")==0)
break;
sendto(sockCli,sendbuf,strlen(sendbuf)+1,0,(SOCKADDR*)&addrSer,len);

recvfrom(sockCli,recvbuf,256,0,(SOCKADDR*)&addrSer,&len);
cout<<"服务器:>"<<recvbuf<<endl;
}
closesocket(sockCli);
return 0;
}


最大的疑问是 客户端程序中设置的端口号 是要连接的服务器端的端口号,那么问题是我在同一台计算机中运行客户端和服务器端,服务器端的端口号是 5566,那客户端程序的端口号就不可能是5566了吧,因为两个程序使用同一个端口号会导致端口号冲突啊,那客户端此时的端口号是多少呢,上述程序中并没有设置啊 。
假设客户端端口号是 系统随机分配的,比如5545,那服务器端是怎么知道这个端口号的呢?
我在郑阿奇的书中看到有个UDP通信程序可以设置自身的IP、端口号,以及要连接的IP和端口号,从而可以实现将同一个程序运行两个实例分别作为客户端和服务器端 (不需要分别写客户端和服务器端程序,只要一个通用的就可以了)。 但那个程序是MFC的,我看不太懂,有谁可以给我一个控制台那样的通用程序吗。

另一个问题是C++语法方面的。我在上述程序中 在 bind方法前加两个冒号, 即::bind(),也不会出错,这是为什么呢,我知道::的左边一般是一个类名,右边是这个类名的方法,那这样写是不是把左边的类名省略了啊,如果不省略,左边应该写一个什么类名呢?
...全文
630 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
走好每一步 2018-03-29
  • 打赏
  • 举报
回复
connect不叫绑定,你自己混淆概念了。 bind才是绑定! TCP三次握手,客户端需要发起连接的。
wuxia2118 2018-03-28
  • 打赏
  • 举报
回复
我觉得我语言已经表述得很清楚了,为什么你们看不懂,难道是我的思维比较怪吗,下面是客户端和服务器的源程序,注意两个程序中都是填的服务器的ip地址
// Server.cpp : TCP通信程序服务器端(控制台版)
#include<iostream.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")
int main(){

	WSADATA wsaData;

 int iErrorcode;
 if(WSAStartup(MAKEWORD(2,2), &wsaData))
 {
  cout<<"Winsock can not be init!";
  WSACleanup();
  return 0;
 }

SOCKET sockSer;
sockSer=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN addrSer,addrCli;
addrSer.sin_family=AF_INET;
addrSer.sin_port=htons(5566);
addrSer.sin_addr.S_un.S_addr=inet_addr("192.168.32.24");  //这个是服务器的IP地址

bind(sockSer,(SOCKADDR*)&addrSer,sizeof(SOCKADDR));
listen(sockSer,5);

SOCKET sockConn;
int len=sizeof(SOCKADDR);

cout<<"服务器等待客户端的连接……"<<endl;

sockConn=accept(sockSer,(SOCKADDR*)&addrCli,&len);
if(sockConn==INVALID_SOCKET){
cout<<"Server Accept Client Connect Fail!"<<endl;
return;}
else{
	cout<<"Server Accept Client Connect Success!"<<endl;
}
char sendbuf[256];
char recvbuf[256];
while(1){
cout<<"服务器说:>";
cin>>sendbuf;
if(strcmp(sendbuf,"bye")==0){
break;}
send(sockConn,sendbuf,strlen(sendbuf)+1,0);
recv(sockConn,recvbuf,256,0);
cout<<"客户端说:>"<<recvbuf<<endl;
}
closesocket(sockSer);
}

// Client.cpp : TCP通信程序客户端(控制台版)

#include<iostream.h>
#include<windows.h>
#pragma comment(lib,"ws2_32.lib") 
int main(){

WSADATA wsaData;
 int iErrorcode;
 if(WSAStartup(MAKEWORD(2,2), &wsaData))
 {
  cout<<"Winsock can not be init!";
  WSACleanup();
  return 0;
 }

SOCKET sockCli;
sockCli=socket(AF_INET,SOCK_STREAM,0);

SOCKADDR_IN addrSer;
addrSer.sin_family=AF_INET;
addrSer.sin_port=htons(5566);
addrSer.sin_addr.S_un.S_addr=inet_addr("192.168.32.24");   //这个也是服务器的IP地址,我把客户端程序放在192.168.32.21这台机器上,两台机器能正常通信

int res=connect(sockCli,(SOCKADDR*)&addrSer,sizeof(SOCKADDR));
if(res){
	cout<<"客户端连接服务器失败"<<endl;
return;	}
else{
	cout<<"客户端连接服务器成功"<<endl;
}
char sendbuf[256];
char recvbuf[256];
while(1){

recv(sockCli,recvbuf,256,0);
cout<<"服务器说:>"<<recvbuf<<endl;
cout<<"客户端说:>";
cin>>sendbuf;
if(strcmp(sendbuf,"bye")==0){
break;}
send(sockCli,sendbuf,strlen(sendbuf)+1,0);
}
WSACleanup();
closesocket(sockCli);
}
wuxia2118 2018-03-27
  • 打赏
  • 举报
回复
可是我实验过,一个TCP控制台通信程序。服务器端的地址是 192.168.2.10,我把服务器端的地址bind为这个,然后把客户端程序的IP地址也设置成这个,客户端程序是运行在另一台主机上(192.168.2.14)的,此时,服务器和客户端两台电脑上的程序能正常通信。 这说明客户端绑定的确实是服务器端的IP地址啊,不是绑定的客户端IP啊
走好每一步 2018-03-27
  • 打赏
  • 举报
回复
直接上代码,不要用你自己的语言了,因为本身你自己没理解好,所以。。。
wuxia2118 2018-03-27
  • 打赏
  • 举报
回复
我现在想知道TCP中的客户端设置的IP地址 是服务器端的IP地址吗, TCP和UDP客户端中设置的IP地址都一样是服务器端的IP地址吧
走好每一步 2018-03-27
  • 打赏
  • 举报
回复
不知道你在说什么了,问题说的UDP,你的实验用TCP来证明。。。
Eleven 2018-03-26
  • 打赏
  • 举报
回复
客户端可以自己调用bind()函数绑定,也可以使用OS给你分配一个默认的,当你调用sendto()函数以后,然后调用getsockname()就知道系统使用的是哪个端口了。
走好每一步 2018-03-26
  • 打赏
  • 举报
回复
1、而客户端如果有bind,则绑定的也是客户端自己的端口吗 是的。 2、客户端有bind并不是为了绑定要连接的服务器端端口 是的。
走好每一步 2018-03-26
  • 打赏
  • 举报
回复
引用 11 楼 wuxia2118 的回复:
但是服务器端必须bind端口,不然客户端不知道往哪里发消息。 那你是说 服务器端绑定的是服务器端的端口,而客户端如果有bind,则绑定的也是客户端自己的端口吗。客户端有bind并不是为了绑定要连接的服务器端端口,对吗。
寄快递的人不一定要写详细地址,收快递的人必须得有详细地址。(我经常寄不重要的快递就不写我自己的地址)
wuxia2118 2018-03-25
  • 打赏
  • 举报
回复
但是服务器端必须bind端口,不然客户端不知道往哪里发消息。 那你是说 服务器端绑定的是服务器端的端口,而客户端如果有bind,则绑定的也是客户端自己的端口吗。客户端有bind并不是为了绑定要连接的服务器端端口,对吗。
走好每一步 2018-03-24
  • 打赏
  • 举报
回复
客户端和服务器只是根据它的功能来划分的。 bind可以随意绑,只要端口不被占用,bind端口的目的只是说为了发送方可以知道往哪里发送消息而已;也就是说客户端可以选择bind端口或采用随机端口的方式。 但是服务器端必须bind端口,不然客户端不知道往哪里发消息。
wuxia2118 2018-03-23
  • 打赏
  • 举报
回复
客户端程序中的bind到底是绑定的服务器端端口,还是客户端自己的端口啊
wuxia2118 2018-03-22
  • 打赏
  • 举报
回复
你说:1.客户端里面比服务器端少一个bind的操作,所以它的端口是随机获取的。 可即使我给客户端里加一条bind语句,它绑定的也是服务器的端口啊,那它自己的端口还是随机获取的吗,它自己这一边的端口要如何绑定呢。 可是这个关键问题我依然没弄明白
smwhotjay 2018-03-21
  • 打赏
  • 举报
回复
::bind() 调用全局api
wuxia2118 2018-03-20
  • 打赏
  • 举报
回复
你说:1.客户端里面比服务器端少一个bind的操作,所以它的端口是随机获取的。 可即使我给客户端里加一条bind语句,它绑定的也是服务器的端口啊,那它自己的端口还是随机获取的吗,它自己这一边的端口要如何绑定呢。
走好每一步 2018-03-20
  • 打赏
  • 举报
回复
1.客户端里面比服务器端少一个bind的操作,所以它的端口是随机获取的。 2.看下UDP协议图,UDP数据包头部包含端口号 3.双冒号显示说明该函数是全局函数,而不是类成员函数;当类中没有同名的成员函数,全局函数的双冒号可以省略。 4.建议,学习UDP协议的时候,下载一个抓包工具,对比着UDP协议图学习一下。 5.自己实现一个简单的协议,深刻理解任意一个通讯协议,再回头看UDP协议,你会觉得很容易理解了。
走好每一步 2018-03-20
  • 打赏
  • 举报
回复
理解网络编程有一点很重要: 系统会为某个端口开辟缓冲区,分别是发送、接收缓冲区。发送函数实际上是将程序的数据压入系统缓冲区(然后再真正发出去),外部数据到来实际上也是压入系统缓冲区(然后程序再去取)。
走好每一步 2018-03-20
  • 打赏
  • 举报
回复
TCP:客户端和服务器有一个连接的过程。在发送数据时最多能发送65535个字节,虽然可靠,但是发送的数据被protocol内部分成了几块,分片发送,所以在用TCP传输的时候,在协议制定上要考虑发送数据连续接收,才能保证一个协议帧的数据正确接收。 UDP:客户端和服务器不需要连接过程。在发送数据时最多能发送65507个字节,UDP容易丢帧,但是发送的65507个字节不会被内部分片,可以整块发送,所以在制定协议时不用TCP那么复杂,发送和接收都很容易实现。工程应用中比较受欢迎。
wuxia2118 2018-03-19
  • 打赏
  • 举报
回复
还有,UDP、TCP程序每次能接收和发送的最多数据量是多少啊,char sendbuf[256]; 我看程序中是256个自己,是不是最多每次只能发送256字节呢

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧