【发布时间】:2018-01-16 06:23:45
【问题描述】:
我有 2 个程序。基本上我正在尝试查看 TCP (SYN, FIN)。
server.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/*
* error - wrapper for perror
*/
void error(char *msg) {
perror(msg);
exit(1);
}
int main(int argc, char **argv) {
int parentfd; /* parent socket */
int childfd; /* child socket */
int portno; /* port to listen on */
int clientlen; /* byte size of client's address */
struct sockaddr_in serveraddr; /* server's addr */
struct sockaddr_in clientaddr; /* client addr */
struct hostent *hostp; /* client host info */
char buf[BUFSIZE]; /* message buffer */
char *hostaddrp; /* dotted decimal host addr string */
int optval; /* flag value for setsockopt */
int n; /* message byte size */
static int cnt;
/*
* check command line arguments
*/
if (argc != 2) {
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(1);
}
portno = atoi(argv[1]);
/*
* socket: create the parent socket
*/
parentfd = socket(AF_INET, SOCK_STREAM, 0);
if (parentfd < 0)
error("ERROR opening socket");
/* setsockopt: Handy debugging trick that lets
* us rerun the server immediately after we kill it;
* otherwise we have to wait about 20 secs.
* Eliminates "ERROR on binding: Address already in use" error.
*/
optval = 1;
setsockopt(parentfd, SOL_SOCKET, SO_REUSEADDR,
(const void *)&optval , sizeof(int));
/*
* build the server's Internet address
*/
bzero((char *) &serveraddr, sizeof(serveraddr));
/* this is an Internet address */
serveraddr.sin_family = AF_INET;
/* let the system figure out our IP address */
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
/* this is the port we will listen on */
serveraddr.sin_port = htons((unsigned short)portno);
/*
* bind: associate the parent socket with a port
*/
if (bind(parentfd, (struct sockaddr *) &serveraddr,
sizeof(serveraddr)) < 0)
error("ERROR on binding");
/*
* listen: make this socket ready to accept connection requests
*/
if (listen(parentfd, 5) < 0) /* allow 5 requests to queue up */
error("ERROR on listen");
/*
* main loop: wait for a connection request, echo input line,
* then close connection.
*/
clientlen = sizeof(clientaddr);
while (1) {
/*
* accept: wait for a connection request
*/
childfd = accept(parentfd, (struct sockaddr *) &clientaddr, &clientlen);
if (childfd < 0)
error("ERROR on accept");
printf("%d: Connected \n", ++cnt);
close(childfd);
}
}
================================================ ====================================
Client.c
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
void tcpConnectComplete(int fd)
{
uint32_t index = 0;
int max_fd, res, optval;
socklen_t optlen;
struct timeval timeout;
int timeoutCount = 0;
fd_set wr_fd;
while(1)
{
max_fd = res = 0;
optval = -1;
timeout.tv_sec = 0;
timeout.tv_usec = ((5 * 1000) / 3 );
FD_ZERO(&wr_fd);
FD_SET(fd, &wr_fd);
res = select(fd+1, NULL, &wr_fd, NULL, &timeout);
if(res == 0 || (res < 0 && errno == EINTR))
{
if(++timeoutCount == 3)
{
break;
}
continue;
}
else if(res < 0)
{
break;
}
if(0 == FD_ISSET(fd, &wr_fd))
{
continue;
}
optval = -1;
optlen = (socklen_t)sizeof(optval);
if(-1 == getsockopt(fd, SOL_SOCKET, SO_ERROR, &optval, &optlen))
{
printf("TCP Connect failed\n");
return;
}
else
{
if(0 == optval)
{
printf("TCP Connect success\n");
}
else
{
printf("TCP Connect failed: optval=%d\n", optval);
}
return;
}
}
}
void tcpConnect(void)
{
struct sockaddr_in addr;
int sockFd = 0;
int enable = 1;
int flags;
/* Created a socket */
if(-1 == (sockFd = socket(AF_INET, SOCK_STREAM, 0)))
{
perror("setsockopt");
return;
}
if(setsockopt(sockFd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
{
perror("setsockopt");
return;
}
/* Set non block mode */
flags = fcntl(sockFd, F_GETFL, NULL);
if (-1 == fcntl(sockFd, F_SETFL, flags | O_NONBLOCK))
{
perror("fcntl");
return;
}
/* Bind to source ip and port */
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(39589);
addr.sin_addr.s_addr = inet_addr("192.168.56.101");
//addr.sin_addr.s_addr = inet_addr("127.0.0.1");
if(-1 == bind(sockFd, (struct sockaddr*)&addr, sizeof(addr)))
{
perror("bind");
return;
}
/* TCP Connect */
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(39591);
addr.sin_addr.s_addr = inet_addr("192.168.56.102");
//addr.sin_addr.s_addr = inet_addr("127.0.0.1");
if(-1 == connect(sockFd, (struct sockaddr*) &addr, sizeof(addr)))
{
perror("connect");
if (errno == EINPROGRESS)
tcpConnectComplete(sockFd);
}
else
{
printf("Connect success\n");
}
close(sockFd);
close(0);
}
int main(void)
{
int i;
for (i = 0; i < 10; i++) {
tcpConnect();
};
return 0;
}
如果同时运行服务器和客户端程序,我会看到以下输出(没有粘贴服务器输出,因为那里没有奇怪的东西):
./client
connect: Operation now in progress
TCP Connect success
connect: Cannot assign requested address
connect: Operation now in progress
TCP Connect success
connect: Cannot assign requested address
connect: Cannot assign requested address
connect: Operation now in progress
TCP Connect success
connect: Cannot assign requested address
connect: Cannot assign requested address
connect: Cannot assign requested address
connect: Cannot assign requested address
我的问题是为什么会出现“无法分配请求的地址”的连接失败?程序有什么问题? 请帮助理解这一点。
【问题讨论】:
-
你能告诉你为什么将客户端绑定到特定地址吗?为什么不能只创建一个套接字并连接到服务器。
-
我希望客户端始终使用相同的 (ip+port)。
-
好吧,在这种情况下,您必须在使用之前关闭该地址。并等到地址空闲
-
服务器机器的ip地址是什么?
-
为什么在 client.c 中使用 bind ?确保在下次提问时在您的问题中发布必要的信息。这次更新问题的详细信息。
标签: linux system-calls connect