socket编程中客户端常用函数 以及简单实现
1 常用函数
1.1 connect()
int connect(int sockfd, const struct sockaddr *servaddr, socklen_taddrlen);
客户端需要调用connect()连接服务器,connect和bind的参数形式一致,区别在于bind的参数是自己的地址,而connect的参数是对方的地址。connect()成功返回0,出错返回-1,程序会阻塞。
1.2 bind():很少用
由于客户端不需要固定的端口号,因此不必调用bind(),客户端的端口号由内核自动分配。注意,客户端不是不允许调用bind(),只是没有必要调用bind()固定一个端口号,服务器也不是必须调用bind(),但如果服务器不调用bind(),内核会自动给服务器分配监听端口,每次启动服务器时端口号都不一样,客户端要连接服务器就会遇到麻烦。
2 客户端的简单实现(C语言)
功能:连接到服务器后,如果服务器发送数据,则返回服务器发送的数据
unsigned char TcpRecvBuf[1520] /* 缓存区,完整的以太帧最大也就1520或1518字节,如果去掉协议部分则可以更小 */ static void Task_TCP_Client (void *pdata) { struct sockaddr_in server, client; int sock, iState; int statusOk = 0; struct ip_addr stIpAddr; IP4_ADDR(&stIpAddr, REMOTE_IP_0, REMOTE_IP_1, REMOTE_IP_2, REMOTE_IP_3); server.sin_family = AF_INET; /* 服务器地址类型为IPV4 */ server.sin_port = htons(80); /* 服务器的端口号为5000 */ server.sin_addr.s_addr = stIpAddr.addr; /* 服务器的IP地址 */ /* * 以下4行为设置客户端的属性,可以不要,有系统自动分配端口号。即不调用bind函数。 */ client.sin_family = AF_INET; client.sin_port = htons( 4000 ); /* 设置客户端的端口 */ client.sin_addr.s_addr = htonl( INADDR_ANY ); bind( sock, (struct sockaddr *)&client, sizeof( client ) );/* 绑定本地接口 */ sock = socket( AF_INET, SOCK_STREAM, 0 ); /* 使用TCP连接 */ /* * 试图与服务器建立连接,阻塞程序 */ iState = connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr)); while(1) { statusOk = read(sock, TcpRecvBuf, sizeof(TcpRecvBuf)); if (statusOk > 0) { statusOk = write(sock, TcpRecvBuf,statusOk); } if (statusOk <= 0){ iState = -1; while (iState == -1) { close( sock ); /* 关闭此连接 */ /* * 下面将重新与服务器建立连接 */ sock = socket( AF_INET, SOCK_STREAM, 0 ); /* 使用TCP连接 */ bind( sock, (struct sockaddr *)&client, sizeof( client ) );/* 绑定本地接口 */ iState = connect(sock, (struct sockaddr *)&server, sizeof( server )); OSTimeDly(100); // 延迟一会儿,(ucos-ii的延迟函数,可以用其它延迟函数替代) } } } }