windows绑定socket端口号失败 端口5002

在线等:多个socket绑定到同一个IP和端口,这样可以吗?
[问题点数:20分,结帖人zhangbinnpu]
在线等:多个socket绑定到同一个IP和端口,这样可以吗?
[问题点数:20分,结帖人zhangbinnpu]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
相关帖子推荐:
本帖子已过去太久远了,不再提供回复功能。Windows socket error: 通常每个套接字地址(协议/网络地址/端口)只允许使用一次 怎么解决呢?
Windows socket error: 通常每个套接字地址(协议/网络地址/端口)只允许使用一次 怎么解决呢?
绑定的端口已经被使用了.在CMD里面执行netstat -ano 看看你要用的端口是否被使用了,被使用了就换一个端口
相关知识等待您来回答
微软专区领域专家1220人阅读
socket INADDR_ANY 监听0.0.0.0地址 socket只绑定端口让路由表决定传到哪个ip
其中INADDR_ANY就是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,或“所有地址”、“任意地址”。
一般情况下,如果你要建立网络服务器,则你要通知服务器操作系统:请在某地址 xxx.xxx.xxx.xxx上的某端口 yyyy上进行侦听,并且把侦听到的数据包发送给我。这个过程,你是通过bind()系统调用完成的。——也就是说,你的程序要绑定服务器的某地址,或者说:把服务器的某地址上的某端口占为已用。服务器操作系统可以给你这个指定的地址,也可以不给你。
如果你的服务器有多个网卡,
而你的服务(不管是在udp端口上侦听,还是在tcp端口上侦听),出于某种原因:可能是你的服务器操作系统可能随时增减IP地址,也有可能是为了省去确定服务器上有什么网络端口(网卡)的麻烦 —— 可以要在调用bind()的时候,告诉操作系统:“我需要在 yyyy 端口上侦听,所以发送到服务器的这个端口,不管是哪个网卡/哪个IP地址接收到的数据,都是我处理的。”这时候,服务器则在0.0.0.0这个地址上进行侦听。例如:
Proto Recv-Q Send-Q Local Address Foreign Address (state)
udp4 0 0 *.7913 *.*&
udp4 0 0 *.7911 *.*
tcp4 0 0 *.ftp *.* LISTEN
以上这些是网络侦听的情况,其中Local Address 为 “*.ftp”、“*.7911”等,代表了服务程序绑定了服务器的所有网卡。
具体一点:
比如你的机器有三个ip &&
& 192.168.1.1 &&
& 202.202.202.202 &&
& 61.1.2.3 &&
& 如果你serv.sin_addr.s_addr=inet_addr(&192.168.1.1&); &&
& 然后监听100端口 &&
& 这时其他机器只有connect & 192.168.1.1:100才能成功。 &&
& connect & 202.202.202.202:100和connect & 61.1.2.3:100都会失败。 &&
& 如果serv.sin_addr.s_addr=htonl(INADDR_ANY); & 的话,无论连接哪个ip都可以连上的。
好了,你明白了侦听INADDR_ANY是什么意思了,那么,我的服务器有N个IP地址,会不会收到重复的数据包?收到数据包后,是不是会重复回复客户端呢?
答案是:不会收到重复的数据包,也不会重复发送数据。
为什么呢?楼上说得对,每一个服务器都有维护着一个路由表。数据包应该向哪里发送,是由路由表决定的。
为什么不会接收到重复的数据包呢?
答:因为客户端只向你的服务器上的唯一一个IP地址发送数据了。
为什么不会重复发送数据包呢?
答:因为发送数据包的路由(路径)是唯一的。如果服务器不知道在发送数据的时候应该向哪个地址发送数据,那么数据就会被发送到“默认网关”上。
如何选择发送数据的路径呢?
答:依照路由表的要求发送。
如果路由表的记录有重复/有冲突呢,这时候如何选择路径呢?
答:路由表记录有优先级别。一般来说,Windows操作系统的路由表记录,如果是重复的话,以后来加入的记录为准,而某些操作系统,象linux/FreeBSD是不允许加入重复的路由表记录的。
&如果是专用的路由器,有路由选择算法,一般来说,到达网络上的某一点的路径是可以有很多条的。路由选择算法可以确定“最好的一条路径”,这条路径要么是延时最小的,要么是费用最低的,要么是带宽最高的,要么是跳点最小的——究竟是如何选择,就看路由器的管理员如何配置了。
对于客户端如果绑定INADDR_ANY,情况类似。对于TCP而言,在connect()系统调用时将其绑顶到一具体的IP地址。选择的依据是该地址所在子网到目标地址是可达的(reachable). 这时通过getsockname()系统调用就能得知具体使用哪一个地址。对于UDP而言, 情况比较特殊。即使使用connect()系统调用也不会绑定到一具体地址。这是因为对UDP使用connect()并不会真正向目标地址发送任何建立连接的数据,也不会验证到目标地址的可达性。它只是将目标地址的信息记录在内部的socket数据结构之中,共以后使用。只有当调用sendto()/send()时,由系统内核根据路由表决定由哪一个地址(网卡)发送UDP
-----------------------------------------------------------------------------
在IP层中有一个路由表:
在MSDOS窗口可以运行命令:netstat -r
来显示路由表。根据路由表的条目从指定的网卡发送数据。
ARP缓存用:arp -a
通常以太网帧的目的MAC地址,是下一跳的MAC地址。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:171287次
积分:2650
积分:2650
排名:第5767名
原创:79篇
转载:129篇
(3)(2)(4)(2)(1)(2)(1)(1)(5)(3)(1)(3)(7)(6)(2)(3)(4)(2)(3)(5)(2)(3)(1)(14)(16)(14)(13)(17)(7)(11)(27)(8)(17)(1)(1)Windows Socket编程,发现这篇文章不错,就拿过来分享下,转载地址:
SOCKET网络编程
(WINDOWS&SOCKET)
网上看了很多Socket的资料,将理解的知识总结下,详细介绍下VC下windows&sockets编程,并结合服务器和客户端的两个实例(TCP/UDP)讲解下。
2.SOCKET相关原理
在网络编程中最常用的方案便是Client/Server&(客户机/服务器)模型。在这种方案中客户应用程序向服务器程序请求服务。一个服务程序通常在一个众所周知的地址监听对服务的请求,也就是说,服务进程一直处于休眠状态(简单的说就是死循环),直到一个客户向这个服务的地址提出了连接请求。在这个时刻,服务程序被&惊醒&并且为客户提供服务-对客户的请求作出适当的反应。
在VC中进行WINSOCK的API编程开发的时候,需要在项目中使用下面的三个文件,否则会出现编译错误。
  1.WINSOCK.H:&这是WINSOCK&API的头文件,需要包含在项目中。
  2.WSOCK32.LIB:&WINSOCK&API连接库文件。在使用中,一定要把它作为项目的非缺省的连接库包含到项目文件中去。&
  3.WINSOCK.DLL:&WINSOCK的动态连接库,位于WINDOWS的安装目录下。
3.SOCKET&API
下面讲解的都是在实例中使用的接口,了解相关定义后我们结合实例讲解。
1.WSAStartup()
此函数在应用程序中初始化Windows&Sockets&DLL&,只有此函数调用成功后,应用程序才可以再调用其他Windows&Sockets&DLL中的API函数。
int&PASCAL&FAR&WSAStartup(WORD&wVersionRequired,&LPWSADATA&lpWSAData);
其返回值为整型,调用方式为PASCAL(即标准类型,PASCAL等于__stdcall),参数有两个,第一个参数为WORD类型,指明了Socket的版本号,第二个参数为WSADATA类型的指针。
若返回值为0,则初始化成功,若不为0则失败。
在程式中调用该函数的形式如下:WSAStartup(MAKEWORD(1,1),&&WSAData),其中MAKEWORD(1,1)表示我们用的是WinSocket1.1版本,WSAata用来存储系统传回的关于WinSocket的资料。
(1)&WORD类型、MAKEWORD、LOBYTE和HIBYTE宏
WORD类型是一个16位的无符号整型,在WTYPES.H中被定义为:
typedef&unsigned&short&WORD;
其目的是提供两个字节的存储,在Socket中这两个字节可以表示主版本号和副版本号。使用MAKEWORD宏可以给一个WORD类型赋值。例如要表示主版本号2,副版本号0,可以使用以下代码:
WORD&wVersionR&&
wVersionRequested&=&MAKEWORD(&2,&0&);
注意低位内存存储主版本号2,高位内存存储副版本号0,其值为0x0002。使用宏LOBYTE可以读取WORD的低位字节,HIBYTE可以读取高位字节。在后面的实例中会应用。
(2)WSADATA类型和LPWSADATA类型
&&&&WSADATA类型是一个结构,描述了Socket库的一些相关信息,其结构定义如下:
typedef&struct&WSAData&{
&&&&&&&&WORD&&&&&&&&&&&&&&&&& wV
&&&&&&&&WORD&&&&&&&&&&&&&&&& wHighV
&&&&&&&&char&&&&&&&&&&&&&&&&&&& szDescription[WSADESCRIPTION_LEN+1];
&&&&&&&&char&&&&&&&&&&&&&&&&&&&& szSystemStatus[WSASYS_STATUS_LEN+1];
&&&&&&&&unsigned&short&&&&&&&&&& iMaxS
&&&&&&&&unsigned&short&&&&&&&&& iMaxUdpDg;
&&&&&&&&char&FAR&*&&&&&&&&&&&&& lpVendorI
}&WSADATA;
typedef&WSADATA&FAR&*LPWSADATA;
&&&&值得注意的就是wVersion字段,存储了Socket的版本类型。LPWSADATA是WSADATA的指针类型。它们通过Socket的初始化函数WSAStartup读取出来。
2.WSACleanup()
这是Socket环境的退出函数。返回值为0表示成功,SOCKET_ERROR表示失败。
3.socket()
SOCKET是socket套接字类型,在WINSOCK2.H中有如下定义:
typedef&unsigned&int&&&&u_
typedef&u_int&&&&&&&&&&&SOCKET;
可知套接字实际上就是一个无符号整型,它将被Socket环境管理和使用。
初始化WinSock的动态连接库后,需要在服务器端建立一个监听的Socket,为此可以调用Socket()函数用来建立这个监听的Socket,并定义此Socket所使用的通信协议。此函数调用成功返回Socket对象,失败则返回INVALID_SOCKET(调用WSAGetLastError()可得知原因,所有WinSocket&的API函数都可以使用这个函数来获取失败的原因。
  SOCKET&PASCAL&FAR&socket(&int&af,&int&type,&int&protocol&)
af: 目前只提供&PF_INET(AF_INET);
type: Socket&的类型&(SOCK_STREAM、SOCK_DGRAM);
protocol: 通讯协定(如果使用者不指定则设为0);
如果要建立的是遵从TCP/IP协议的socket,第二个参数type应为SOCK_STREAM,为UDP(数据报)的socket,应为SOCK_DGRAM。
l&SOCK_STREAM:这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类型,这个socket是使用TCP来进行传输。
l&SOCK_DGRAM:这个协议是无连接的、固定长度的传输调用。该协议是不可靠的,使用UDP来进行它的连接。
套接字将被创建、设置、用来发送和接收数据,最后会被关闭。
接下来要为服务器端定义的这个监听的Socket指定一个地址及端口(Port),这样客户端才知道待会要连接哪一个地址的哪个端口,为此我们要调用bind()函数,该函数调用成功返回0,否则返回SOCKET_ERROR。
  int&PASCAL&FAR&bind(&SOCKET&s,&const&struct&sockaddr&FAR&*name,int&namelen&);
s:Socket对象名;
name:Socket的地址值,这个地址必须是执行这个程式所在机器的IP地址;
namelen:name的长度;&
如果使用者不在意地址或端口的值,那么可以设定地址为INADDR_ANY,及Port为0,Windows&Sockets&会自动将其设定适当之地址及Port&(1024&到&5000之间的值)。此后可以调用getsockname()函数来获知其被设定的值。
5.sockaddr_in、in_addr类型,inet_addr、inet_ntoa函数,sockaddr
sockaddr_in定义了socket发送和接收数据包的地址,定义:
struct&sockaddr_in
&&&&&&&&short&& & sin_
&&&&&&&&u_short& sin_
&&&&&&&&struct&in_addr& sin_
&&&&&&&&char&&&& sin_zero[8];
其中in_addr的定义如下:
struct&in_addr&
&&&&&&&& union&{
&&&&&&&&&&&&&&&& struct&{&u_char&s_b1,s_b2,s_b3,s_b4;&}&S_un_b;
&&&&&&&&&&&&&&&& struct&{&u_short&s_w1,s_w2;&}&S_un_w;
&&&&&&&&&&&&&&&& u_long&S_
首先阐述in_addr的含义,很显然它是一个存储ip地址的联合体(union),有三种表达方式:
第一种用四个字节来表示IP地址的四个数字;
第二种用两个双字节来表示IP地址;
第三种用一个长整型来表示IP地址。
给in_addr赋值的一种最简单方法是使用inet_addr函数,它可以把一个代表IP地址的字符串赋值转换为in_addr类型,如
addrto.sin_addr.s_addr=inet_addr(&192.168.0.2&);
其反函数是inet_ntoa,可以把一个in_addr类型转换为一个字符串。
sockaddr_in的含义比in_addr的含义要广泛,其各个字段的含义和取值如下:
第一个字段short&&&sin_family,代表网络地址族,如前所述,只能取值AF_INET;
第二个字段u_short&sin_port,代表IP地址端口,由程序员指定;
第三个字段struct&in_addr&sin_addr,代表IP地址;
第四个字段char&&&&sin_zero[8],是为了保证sockaddr_in与SOCKADDR类型的长度相等而填充进来的字段。
sockaddr类型是用来表示Socket地址的类型,同上面的sockaddr_in类型相比,sockaddr的适用范围更广,因为sockaddr_in只适用于TCP/IP地址。Sockaddr的定义如下:
struct&sockaddr&{
&u_short&&&&sa_
&char&&&&&&&sa_data[14];
可知sockaddr有16个字节,而sockaddr_in也有16个字节,所以sockaddr_in是可以强制类型转换为sockaddr的。事实上也往往使用这种方法。
6.listen()
当服务器端的Socket对象绑定完成之后,服务器端必须建立一个监听的队列来接收客户端的连接请求。listen()函数使服务器端的Socket&进入监听状态,并设定可以建立的最大连接数(目前最大值限制为&5,&最小值为1)。该函数调用成功返回0,否则返回SOCKET_ERROR。
  int&PASCAL&FAR&listen(&SOCKET&s,&int&backlog&);
s:需要建立监听的Socket;
backlog:最大连接个数;
 & 服务器端的Socket调用完listen()后,如果此时客户端调用connect()函数提出连接申请的话,Server&端必须再调用accept()&函数,这样服务器端和客户端才算正式完成通信程序的连接动作。为了知道什么时候客户端提出连接要求,从而服务器端的Socket在恰当的时候调用&accept()函数完成连接的建立,我们就要使用WSAAsyncSelect()函数,让系统主动来通知我们有客户端提出连接请求了。该函数调用成功&返回0,否则返回SOCKET_ERROR。
  int&PASCAL&FAR&WSAAsyncSelect(&SOCKET&s,&HWND&hWnd,unsigned&int&wMsg,&long&lEvent&);
s:Socket&对象;
hWnd&:接收消息的窗口句柄;
wMsg:传给窗口的消息;
lEvent:被注册的网络事件,也即是应用程序向窗口发送消息的网路事件,该值为下列值FD_READ、FD_WRITE、FD_OOB、&FD_ACCEPT、FD_CONNECT、FD_CLOSE的组合,各个值的具体含意为FD_READ:希望在套接字S收到数据时收到消&息;FD_WRITE:希望在套接字S上可以发送数据时收到消息;FD_ACCEPT:希望在套接字S上收到连接请求时收到消息;FD_CONNECT:&希望在套接字S上连接成功时收到消息;FD_CLOSE:希望在套接字S上连接关闭时收到消息;FD_OOB:希望在套接字S上收到带外数据时收到消息。&具体应用时,wMsg应是在应用程序中定义的消息名称,而消息结构中的lParam则为以上各种网络事件名称。所以,可以在窗口处理自定义消息函数中使用&以下结构来响应Socket的不同事件:  
switch(lParam) 
 case&FD_READ:
  &…  
 case&FD_WRITE:
7.accept()
当Client提出连接请求时,Server&端hwnd视窗会收到Winsock&Stack送来我们自定义的一个消息,这时,我们可以分析lParam,然后调用相关的函数来处理此事件。为了使服务器端接受客户端的连接请求,就要使用&accept()&函数,该函数新建一Socket与客户端的Socket相通,原先监听之Socket继续进入监听状态,等待他人的连接要求。该函数调用成功返回一个新产&生的Socket对象,否则返回INVALID_SOCKET。
  SOCKET&PASCAL&FAR&accept(&SCOKET&s,&struct&sockaddr&FAR&*addr,int&FAR&*addrlen&);
s:Socket的识别码;
addr:存放来连接的客户端的地址;
addrlen:addr的长度
8.connect()
Connect用于客户端想服务器发起连接。
格&式:&int&PASCAL&FAR&connect(&SOCKET&s,const&struct&sockaddr&FAR&*name,int&namelen&);
参&数:&s&Socket&的识别码
name&此&Socket&想要连接的对方位址
namelen&name的长度
传回值:成功&-&0
失败&-&SOCKET_ERROR&(呼叫WSAGetLastError()可得知原因)
说明:&此函式用来向对方要求建立连接。若是指定的对方位址为&0&的话,会传回错误值。当连接建立完成後,使用者即可利用此一&Socket&来做传送或接收资料之用了。
9.sendto(),send()函数
在Socket中有两套发送和接收函数,一是sendto和recvfrom;二是send和recv。前一套在函数参数中要指明地址(UDP协议);而后一套需要先将套接字和一个地址绑定,然后直接发送和接收,不需绑定地址。
sendto的定义如下:
int&PASCAL&FAR&sendto&(SOCKET&s,&const&char&FAR&*&buf,&int&len,&int&flags,&const&struct&sockaddr&FAR&*to,&int&tolen);
第一个参数就是套接字;
第二个参数是要传送的数据指针;
第三个参数是要传送的数据长度(字节数);
第四个参数是传送方式的标识,如果不需要特殊要求则可以设置为0,其它值请参考MSDN;
第五个参数是目标地址,注意这里使用的是sockaddr的指针;
第六个参数是地址的长度;
返回值为整型,如果成功,则返回发送的字节数,失败则返回SOCKET_ERROR。
send函数有四个参数与sendto函数的前四个参数是一样的。
10.recvfrom(),recv()函数
int&WSAAPI&recvfrom(IN&SOCKET&s,char&FAR&*&buf,int&len,int&flags,sockaddr&FAR&*&from,int&&*&fromlen&);
第一个参数就是套接字;
第二个参数是要接收消息的char数组的指针;
第三个参数是要接收的数据长度(字节数);
第四个参数是接收方式的标识,如果不需要特殊要求则可以设置为0;
第五个参数是接收地址的结构指针,存放接收到对方的的地址信息;
第六个参数是地址的长度的指针(&);
返回值为整型,如果成功,则返回接收的字节数,失败则返回SOCKET_ERROR。
recv函数有四个参数与recvfrom函数的前四个参数是一样的。
11.sleep()函数
线程挂起函数,表示线程挂起一段时间。Sleep(1000)表示挂起一秒。定义于WINBASE.H头文件中。WINBASE.H又被包含于WINDOWS.H中,然后WINDOWS.H被WINSOCK2.H包含。
12.recvfrom(),recv()函数
int&WSAAPI&recvfrom(IN&SOCKET&s,char&FAR&*&buf,int&len,int&flags,sockaddr&FAR&*&from,int&&*&fromlen&);
第一个参数就是套接字;
第二个参数是要接收消息的char数组的指针;
第三个参数是要接收的数据长度(字节数);
第四个参数是接收方式的标识,如果不需要特殊要求则可以设置为0;
第五个参数是接收地址的结构指针,存放接收到对方的的地址信息;
第六个参数是地址的长度的指针(&);
返回值为整型,如果成功,则返回接收的字节数,失败则返回SOCKET_ERROR。
recv函数有四个参数与recvfrom函数的前四个参数是一样的。
13.closesocket()
关闭套接字,其参数为SOCKET类型。成功返回0,失败返回SOCKET_ERROR。
4.TCP/UDP&Socket流程图
1.UDP流程图
2.TCP流程图
以下实现在我本地测试通过
1. UDP实现
(1) UDP Server
#include &stdio.h&
/* Windows socket头文件 */
#include &Winsock2.h&
/* 网络API的动态链接库 */
#pragma comment(lib, &ws2_32.lib&)
void main()
SOCKET uiFdS
WSADATA wsaD
char szbuffer[1024] = &\0&;
struct sockaddr_in stServerA
struct sockaddr_in stClientA
int iAddrlen = sizeof(sockaddr_in);
/* 调用Windows Sockets DLL,成功后才能使用socket系列函数 */
if (0 != WSAStartup(MAKEWORD(2,1), &wsaData))
printf(&Winsock init failed!\r\n&);
WSACleanup();
memset(&stServerAddr, 0, sizeof(stServerAddr));
memset(&stClientAddr, 0, sizeof(stClientAddr));
/* 服务器地址 */
stServerAddr.sin_family = AF_INET;
/* 监听端口 */
stServerAddr.sin_port = htons(6000);
stServerAddr.sin_addr.s_addr = INADDR_ANY;
/* 服务器端创建socket, 报文模式(UDP)*/
uiFdSocket = socket(AF_INET, SOCK_DGRAM, 0);
/* 绑定端口号 */
bind(uiFdSocket, (struct sockaddr*)&stServerAddr, sizeof(sockaddr_in));
while(true)
printf(&waiting client send msg now...\r\n&);
if (SOCKET_ERROR != recvfrom(uiFdSocket,szbuffer,sizeof(szbuffer),0,(struct
sockaddr*)&stClientAddr, &iAddrlen))
printf(&Received datagram from %s--%s\n&, inet_ntoa(stClientAddr.sin_addr),
szbuffer);
sendto(uiFdSocket, szbuffer, sizeof(szbuffer), 0, (struct sockaddr*)&stClientAddr,
iAddrlen);
closesocket(uiFdSocket);
(2) UDP Client
#include &stdio.h&
/* Windows socket头文件 */
#include &Winsock2.h&
/* 网络API的动态链接库 */
#pragma comment(lib, &ws2_32.lib&)
void main()
SOCKET uiF
WSADATA wsaD
struct sockaddr_in stServerA
int iAddrlen = sizeof(sockaddr_in);
char szbuffer[1024] = &\0&;
if (0 != WSAStartup(MAKEWORD(2,1),&wsaData))
printf(&Winsock init faied!\r\n&);
WSACleanup();
/* 服务器监听的端口和地址 */
memset(&stServerAddr, 0, sizeof(stServerAddr));
stServerAddr.sin_family = AF_INET;
stServerAddr.sin_port = htons(6000);
stServerAddr.sin_addr.s_addr = inet_addr(&127.0.0.1&);
printf(&Now connecting the server...\r\n&);
uiFdsocket = socket(AF_INET, SOCK_DGRAM, 0);
while(true)
printf(&Input message here...\r\n&);
scanf(&%s&, szbuffer);
gets(szbuffer);
if(strcmp(szbuffer, &bye&) == 0)
printf(&exit\r\n&);
Sleep(100);
closesocket(uiFdsocket);
if(SOCKET_ERROR != sendto(uiFdsocket, szbuffer,sizeof(szbuffer), 0, (struct
sockaddr*)&stServerAddr, iAddrlen))
Sleep(100);
if (SOCKET_ERROR != recvfrom(uiFdsocket, szbuffer, sizeof(szbuffer), 0, (struct sockaddr*)&stServerAddr, &iAddrlen))
printf(&recive from server:%s\r\n&, szbuffer);
closesocket(uiFdsocket);
2. TCP 实现
(1) TCP Server
#include &winsock2.h&
#include &stdio.h&
#include &windows.h&
#pragma comment(lib,&ws2_32.lib&)
int main(int argc, char* argv[]){
//判断是否输入了端口号
if(argc!=2){
printf(&Usage: %s PortNumber\n&,argv[0]);
//把端口号转化成整数
if((port = atoi(argv[1]))==0){
printf(&端口号有误\n&);
//初始化套接字DLL
if(WSAStartup(MAKEWORD(2,2),&wsa)!=0){
printf(&套接字初始化失败!\n&);
//创建套接字
SOCKET serverS
if((serverSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){
printf(&创建套接字失败!\n&);
struct sockaddr_in serverA
memset(&serverAddress,0,sizeof(sockaddr_in));
serverAddress.sin_family=AF_INET;
serverAddress.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
serverAddress.sin_port = htons(port);
if(bind(serverSocket,(sockaddr*)&serverAddress,sizeof(serverAddress))==SOCKET_ERROR){
printf(&套接字绑定到端口失败! 端口: %d\n&,port);
//进入侦听状态
if(listen(serverSocket,SOMAXCONN)==SOCKET_ERROR){
printf(&侦听失败!&);
printf(&Server %d is listening......\n&,port);
SOCKET clientS//用来和客户端通信的套接字
struct sockaddr_in clientA//用来和客户端通信的套接字地址
memset(&clientAddress,0,sizeof(clientAddress));
int addrlen = sizeof(clientAddress);
//接受连接
if((clientSocket=accept(serverSocket,(sockaddr*)&clientAddress,&addrlen))==INVALID_SOCKET){
printf(&接受客户端连接失败!&);
printf(&Accept connection from %s\n&,inet_ntoa(clientAddress.sin_addr));
char buf[4096];
//接收数据
memset(buf,0x00,sizeof(buf));
if((bytes=recv(clientSocket,buf,sizeof(buf),0))==SOCKET_ERROR){
printf(&接收数据失败!\n&);
buf[bytes]='\0';
printf(&Message from %s: %s\n&,inet_ntoa(clientAddress.sin_addr),buf);
if(send(clientSocket,buf,bytes,0)==SOCKET_ERROR){
printf(&发送数据失败!&);
//清理套接字占用的资源
WSACleanup();
(2) TCP Client
#include &winsock2.h&
#include &stdio.h&
#include &windows.h&
#pragma comment(lib,&ws2_32.lib&)
int main(int argc, char* argv[]){
//判断是否输入了IP地址和端口号
if(argc!=3){
printf(&Usage: %s IPAddress PortNumber\n&,argv[0]);
//把字符串的IP地址转化为u_long
if((ip=inet_addr(argv[1]))==INADDR_NONE){
printf(&不合法的IP地址:%s&,argv[1]);
//把端口号转化成整数
if((port = atoi(argv[2]))==0){
printf(&端口号有误!&);
printf(&Connecting to %s:%d......\n&,inet_ntoa(*(in_addr*)&ip),port);
//初始化套接字DLL
if(WSAStartup(MAKEWORD(2,2),&wsa)!=0){
printf(&套接字初始化失败!&);
//创建套接字
if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){
printf(&创建套接字失败!&);
struct sockaddr_in serverA
memset(&serverAddress,0,sizeof(sockaddr_in));
serverAddress.sin_family=AF_INET;
serverAddress.sin_addr.S_un.S_addr =
serverAddress.sin_port = htons(port);
//建立和服务器的连接
if(connect(sock,(sockaddr*)&serverAddress,sizeof(serverAddress))==SOCKET_ERROR){
printf(&建立连接失败!&);
char buf[4096];
printf(&&&);
//从控制台读取一行数据
memset(buf,0,sizeof(buf));
gets(buf);
buf[strlen(buf)] = '\0';
//发送给服务器
if(send(sock,buf,strlen(buf),0)==SOCKET_ERROR){
printf(&发送数据失败!\n&);
if((bytes=recv(sock,buf,strlen(buf),0))==SOCKET_ERROR){
printf(&接收数据失败!\n&);
buf[bytes]='\0';
printf(&Message from %s: %s\n&,inet_ntoa(serverAddress.sin_addr),buf);
//清理套接字占用的资源
WSACleanup();
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:43410次
排名:千里之外
原创:50篇
转载:21篇
评论:41条
(3)(1)(1)(2)(3)(1)(1)(3)(1)(2)(4)(2)(1)(1)(1)(4)(1)(1)(8)(2)(3)(1)(2)(1)(1)(3)(3)(6)(3)(1)(1)(4)

我要回帖

更多关于 socket端口复用 的文章

 

随机推荐