C 客户端服务器连接被拒绝
C Client Server Connection Refused
我有一台笔记本电脑 运行ning windows 10 并在 Oracle VM Virtualbox Machine 中安装了 ubuntu。我有以下服务器和客户端源代码。我 运行 先是服务器,然后是客户端。但它给了我一个拒绝连接。试过netstat -ntlp 发现居然没有端口监听我输入的具体端口
server.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/utsname.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<unistd.h>
int _GetHostName(char *buffer, int lenght);
const char MESSAGE[]="Hello, World!\n";
const int BACK_LOG=5;
int main(int argc, char *argv[]){
int serverSocket=0, on=0, port=0, status=0, childPid=0;
struct hostent *hostPtr=NULL;
char hostname[80]="";
struct sockaddr_in serverName={0};
if(2!= argc){
fprintf(stderr, "Usage : %s <port>\n", argv[0]);
exit(1);
}
port=atoi(argv[1]);
serverSocket=socket(PF_INET,SOCK_STREAM, IPPROTO_TCP);
if(-1==serverSocket){
perror("socket()");
exit(1);
}
on=1;
status=setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
if(-1==status){
perror("setsockopt(...,SO_REUSEADDRE,...)");
}
{
struct linger linger={0};
linger.l_onoff=1;
linger.l_linger=30;
status=setsockopt(serverSocket, SOL_SOCKET, SO_LINGER, (const char*)&linger, sizeof(linger));
if(-1==status){
perror("setsockopt(...,SO_LINGER,...)");
}
}
status=_GetHostName(hostname, sizeof(hostname));
if(-1==status){
perror("_GetHostName()");
exit(1);
}
hostPtr=gethostbyname(hostname);
if(NULL==hostPtr){
perror("gethostbyname()");
exit(1);
}
(void)memset(&serverName,0,sizeof(serverName));
(void)memcpy(&serverName.sin_addr, hostPtr->h_addr,hostPtr->h_length);
serverName.sin_family=AF_INET;
serverName.sin_port=htons(port);
status=bind(serverSocket, (struct sockaddr*)&serverName,sizeof(serverName));
if(-1==status){
perror("bind");
exit(1);
}
status=listen(serverSocket, BACK_LOG);
if(-1==status){
perror("listen()");
exit(1);
}
for(;;){
struct sockaddr_in clientName={0};
int slaveSocket, clientLength=sizeof(clientName);
(void)memset(&clientName,0,sizeof(clientName));
slaveSocket=accept(serverSocket,(struct sockaddr*)&clientName, & clientLength);
if(-1==slaveSocket){
perror("accept()");
exit(1);
}
childPid=fork();
switch(childPid){
case -1:perror("fork()");
exit(1);
case 0: close(serverSocket);
if(-1==getpeername(slaveSocket, (struct sockaddr*)&clientName, &clientLength)){
perror("getpeername()");
}else{
printf("Connection request from %s \n", inet_ntoa(clientName.sin_addr));
}
/*
Server Application specific code here
response to client
*/
write(slaveSocket,MESSAGE,strlen(MESSAGE));
close(slaveSocket);
exit(0);
default:close(slaveSocket);
}
}
return 0;
}
int _GetHostName(char *buffer,int length){
struct utsname sysname={0};
int status=0;
status=uname(&sysname);
if(-1!=status){
strncpy(buffer,sysname.nodename,length);
}
return(status);
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
int main(int argc, char *argv[]){
int clientSocket, remotePort, status=0;
struct hostent *hostPtr=NULL;
struct sockaddr_in serverName={0};
char buffer[256]="";
char *remoteHost=NULL;
if(3!=argc){
fprintf(stderr, "Usage: %s <serverHost> <serverPort> \n",argv[0]);
exit(1);
}
remoteHost=argv[1];
remotePort=atoi(argv[2]);
clientSocket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
if(-1==clientSocket){
perror("socket()");
exit(1);
}
hostPtr=gethostbyname(remoteHost);
if(NULL==hostPtr){
hostPtr=gethostbyaddr(remoteHost,strlen(remoteHost), AF_INET);
if(NULL==hostPtr){
perror("Error resolving server address ");
exit(1);
}
}
serverName.sin_family=AF_INET;
serverName.sin_port=htons(remotePort);
(void)memcpy(&serverName.sin_addr,hostPtr->h_addr,hostPtr->h_length);
status=connect(clientSocket,(struct sockaddr*)&serverName,sizeof(serverName));
if(-1==status){
perror("connect()");
exit(1);
}
//CLIENT SPECIFIC HERE
while(0 < (status=read(clientSocket, buffer,sizeof(buffer)-1)))
printf("%d: %s", status, buffer);
if(-1==status)perror("read()");
close(clientSocket);
return 0;
}
如您在服务器控制台中所见,对 gethostbyname 的调用失败。这个函数设置的是h_errno,不是errno,所以不能用perror来输出错误。这就是为什么你看到它声称 "success".
不过我看不出在这里使用 gethostbyname 有什么意义,大多数服务器在用户未指定地址时默认使用 INADDR_ANY。
正如 Joni 已经指出的那样,您的程序在 server.c 中的 gethostbyname()
处失败,然后退出。因此没有端口被绑定,因为你的程序不再是 运行。
如果不是真的需要,请不要使用 gethostbyname()
函数,直接设置 sin_addr
,就像以下示例之一:
// let the kernel fill in the address of your interface for you automatically
serverName.sin_addr.s_addr = htonl(INADDR_ANY);
// use a loopback address (127.0.0.1) = localhost
serverName.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
// use whatever address you like
serverName.sin_addr.s_addr = inet_addr("127.1.1.1");
不要忘记删除行
memcpy(&serverName.sin_addr, hostPtr->h_addr,hostPtr->h_length);
in server.c 当你像上面的例子一样设置 sin_addr
时。
刚刚弄明白了。其实代码没有问题。之所以在下面这行特别出错,是因为我刚刚在虚拟盒子中安装了ubuntu之后,我更改了ubuntu的设备名称,而没有更改etc/hosts
。
hostPtr=gethostbyname(hostname);
if(NULL==hostPtr){
perror("gethostbyname()");
exit(1);
}
我有一台笔记本电脑 运行ning windows 10 并在 Oracle VM Virtualbox Machine 中安装了 ubuntu。我有以下服务器和客户端源代码。我 运行 先是服务器,然后是客户端。但它给了我一个拒绝连接。试过netstat -ntlp 发现居然没有端口监听我输入的具体端口
server.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/utsname.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<unistd.h>
int _GetHostName(char *buffer, int lenght);
const char MESSAGE[]="Hello, World!\n";
const int BACK_LOG=5;
int main(int argc, char *argv[]){
int serverSocket=0, on=0, port=0, status=0, childPid=0;
struct hostent *hostPtr=NULL;
char hostname[80]="";
struct sockaddr_in serverName={0};
if(2!= argc){
fprintf(stderr, "Usage : %s <port>\n", argv[0]);
exit(1);
}
port=atoi(argv[1]);
serverSocket=socket(PF_INET,SOCK_STREAM, IPPROTO_TCP);
if(-1==serverSocket){
perror("socket()");
exit(1);
}
on=1;
status=setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
if(-1==status){
perror("setsockopt(...,SO_REUSEADDRE,...)");
}
{
struct linger linger={0};
linger.l_onoff=1;
linger.l_linger=30;
status=setsockopt(serverSocket, SOL_SOCKET, SO_LINGER, (const char*)&linger, sizeof(linger));
if(-1==status){
perror("setsockopt(...,SO_LINGER,...)");
}
}
status=_GetHostName(hostname, sizeof(hostname));
if(-1==status){
perror("_GetHostName()");
exit(1);
}
hostPtr=gethostbyname(hostname);
if(NULL==hostPtr){
perror("gethostbyname()");
exit(1);
}
(void)memset(&serverName,0,sizeof(serverName));
(void)memcpy(&serverName.sin_addr, hostPtr->h_addr,hostPtr->h_length);
serverName.sin_family=AF_INET;
serverName.sin_port=htons(port);
status=bind(serverSocket, (struct sockaddr*)&serverName,sizeof(serverName));
if(-1==status){
perror("bind");
exit(1);
}
status=listen(serverSocket, BACK_LOG);
if(-1==status){
perror("listen()");
exit(1);
}
for(;;){
struct sockaddr_in clientName={0};
int slaveSocket, clientLength=sizeof(clientName);
(void)memset(&clientName,0,sizeof(clientName));
slaveSocket=accept(serverSocket,(struct sockaddr*)&clientName, & clientLength);
if(-1==slaveSocket){
perror("accept()");
exit(1);
}
childPid=fork();
switch(childPid){
case -1:perror("fork()");
exit(1);
case 0: close(serverSocket);
if(-1==getpeername(slaveSocket, (struct sockaddr*)&clientName, &clientLength)){
perror("getpeername()");
}else{
printf("Connection request from %s \n", inet_ntoa(clientName.sin_addr));
}
/*
Server Application specific code here
response to client
*/
write(slaveSocket,MESSAGE,strlen(MESSAGE));
close(slaveSocket);
exit(0);
default:close(slaveSocket);
}
}
return 0;
}
int _GetHostName(char *buffer,int length){
struct utsname sysname={0};
int status=0;
status=uname(&sysname);
if(-1!=status){
strncpy(buffer,sysname.nodename,length);
}
return(status);
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
int main(int argc, char *argv[]){
int clientSocket, remotePort, status=0;
struct hostent *hostPtr=NULL;
struct sockaddr_in serverName={0};
char buffer[256]="";
char *remoteHost=NULL;
if(3!=argc){
fprintf(stderr, "Usage: %s <serverHost> <serverPort> \n",argv[0]);
exit(1);
}
remoteHost=argv[1];
remotePort=atoi(argv[2]);
clientSocket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
if(-1==clientSocket){
perror("socket()");
exit(1);
}
hostPtr=gethostbyname(remoteHost);
if(NULL==hostPtr){
hostPtr=gethostbyaddr(remoteHost,strlen(remoteHost), AF_INET);
if(NULL==hostPtr){
perror("Error resolving server address ");
exit(1);
}
}
serverName.sin_family=AF_INET;
serverName.sin_port=htons(remotePort);
(void)memcpy(&serverName.sin_addr,hostPtr->h_addr,hostPtr->h_length);
status=connect(clientSocket,(struct sockaddr*)&serverName,sizeof(serverName));
if(-1==status){
perror("connect()");
exit(1);
}
//CLIENT SPECIFIC HERE
while(0 < (status=read(clientSocket, buffer,sizeof(buffer)-1)))
printf("%d: %s", status, buffer);
if(-1==status)perror("read()");
close(clientSocket);
return 0;
}
如您在服务器控制台中所见,对 gethostbyname 的调用失败。这个函数设置的是h_errno,不是errno,所以不能用perror来输出错误。这就是为什么你看到它声称 "success".
不过我看不出在这里使用 gethostbyname 有什么意义,大多数服务器在用户未指定地址时默认使用 INADDR_ANY。
正如 Joni 已经指出的那样,您的程序在 server.c 中的 gethostbyname()
处失败,然后退出。因此没有端口被绑定,因为你的程序不再是 运行。
如果不是真的需要,请不要使用 gethostbyname()
函数,直接设置 sin_addr
,就像以下示例之一:
// let the kernel fill in the address of your interface for you automatically
serverName.sin_addr.s_addr = htonl(INADDR_ANY);
// use a loopback address (127.0.0.1) = localhost
serverName.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
// use whatever address you like
serverName.sin_addr.s_addr = inet_addr("127.1.1.1");
不要忘记删除行
memcpy(&serverName.sin_addr, hostPtr->h_addr,hostPtr->h_length);
in server.c 当你像上面的例子一样设置 sin_addr
时。
刚刚弄明白了。其实代码没有问题。之所以在下面这行特别出错,是因为我刚刚在虚拟盒子中安装了ubuntu之后,我更改了ubuntu的设备名称,而没有更改etc/hosts
。
hostPtr=gethostbyname(hostname);
if(NULL==hostPtr){
perror("gethostbyname()");
exit(1);
}