建立TCP/IP连接
刚接触这部分内容 照着书做的 大致了解了一下 但是程序运行的时候服务器端始终无法收到用户端的请求 劳烦老手帮忙看一下 稍加讲解.... 感谢!
这是用户端
#pragma comment(lib,"wsock32.lib")#include <stdio.h>#include <WinSock2.h>unsigned short port;char *hostname;int initsockets();void getargument(int argc,char** argv);void errorprint(char* x);void userhelp();int main(int argc,char** argv){ SOCKET clientfd; int err; struct sockaddr_in serveraddr; struct hostent* ptrhost; char response[4096]; char *msg="HELLO SERVER"; if(argc!=3) { userhelp(); return 1; } getargument(argc,argv); initsockets(); //创建套接字 clientfd=socket(AF_INET,SOCK_STREAM,0); //创建失败 if(clientfd==INVALID_SOCKET) { errorprint("no more socket resources"); return 1; } //解析地址 if(atoi(hostname)) { u_long ip_addr=inet_addr(hostname); ptrhost=gethostbyaddr((char*)&ip_addr,sizeof(u_long),AF_INET); } else ptrhost=gethostbyname(hostname); if(!ptrhost) { errorprint("cannot resolve hostname"); return 1; } //设置服务器端地址选项 serveraddr.sin_family=AF_INET; //将本机地址复制给服务器端地址 memcpy((char*)&(serveraddr.sin_addr),ptrhost->h_addr_list,ptrhost->h_length); serveraddr.sin_port=htons(port);//将一个无符号短整型数值转换为网络字节序,即大端模式(big-endian) //连接服务器 err=connect(clientfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr)); //连接失败 if(err=INVALID_SOCKET) { errorprint("cannot connect to server"); return 1; } //连接成功后输出信息 printf("You are connected to the server \n"); //发送消息到服务器端 send(clientfd,msg,strlen(msg)+1,0); memset(response,0,sizeof(response)); //接收来自服务器端的消息 recv(clientfd,msg,strlen(msg)+1,0); printf("server says %s\n",response); //关闭套接字 closesocket(clientfd); //释放winsocket初始化时占用的资源 WSACleanup(); return 0;}int initsockets(){ WSADATA wsadata; WORD sockversion; int err; sockversion=MAKEWORD(2,2); err=WSAStartup(sockversion,&wsadata); if(err!=0) { printf("Error %d : Winsock not available \n", err); return 1; } return 0;}void getargument(int argc,char**argv){ int i; for(i=1;i<argc;i++) { if(argv[i][0]=='-') { switch(tolower(argv[i][1])) { case 'p': if(strlen(argv[i])>3) port=atoi(&argv[i][3]); break; case 'h': hostname=&argv[i][3]; break; default: userhelp(); break; } } } return;}void errorprint(char * x){ printf("Error %d : %s\n",WSAGetLastError(),x);}void userhelp(){ printf("user help: -h:str -p:int\n"); printf(" -h:str The Host name \n"); printf(" -p:int The Port number to use\n"); ExitProcess(-1);}
listenfd=socket(AF_INET,SOCK_STREAM,0);//创建TCP流套接字
if(listenfd==INVALID_SOCKET)//如果创建套接字失败
{
printf("Error: out of socket resources\n");
return 1;
}
if(atoi(hostname))//如果是IP地址
{
u_long ip_addr=inet_addr(hostname);//若字符串有效则为32位二进制网络字节序的IPV4地址,否则为INADDR_NONE
ptrhost=gethostbyaddr((char*)&ip_addr,sizeof(u_long),AF_INET);//根据IP地址好到与之匹配的主机名
}
else//如果是主机名
ptrhost=gethostbyname(hostname);//根据主机名获取hosten的指针
if(!ptrhost) //如果解析失败
{
errorprint("cannot resolve hostname\n");
return 1;
}
//设置服务器地址
serveraddr.sin_family=AF_INET;//设置地址族为PF——INET
serveraddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//将一个通配的Internet地址转换成无符号长整形的网络字节序数
serveraddr.sin_port=htons(port);//将端口号转换成无符号断整型的网络字节序数
err=bind(listenfd,(const struct sockaddr*)&serveraddr,sizeof(serveraddr));//将套接字与服务器地址绑定
if(err==INVALID_SOCKET)//如果绑定失败
{
errorprint("unable to bind socket\n");
return 1;
}
err=listen(listenfd,SOMAXCONN);//开始侦听,设置等待连接的最大队列长度为SOMAXCONN(由系统决定),默认为5个
if(err==INVALID_SOCKET)//如果侦听失败
{
errorprint("listen failed\n");
return 1;
}
loopcontrol(listenfd,1);
printf("Server is down\n");
WSACleanup();//释放Win素材oket初始化时占用的资源
return 0;
}
void initial()
{
hostname="127.0.0.1";
maxservice=3;
port=8088;
}
void getargments(int argc,char** argv)
{
int i;
for(i=1;i<argc;i++)
{
if(argv[i][0]=='-')//参数的第一个字符是'-'
{
switch(tolower(argv[i][1]))//把字符转换成小写字母,非字母字符不做出处理
{
case 'p'://若为端口号
if(strlen(argv[i])>3)
port=atoi(&argv[i][3]);
break;
case 'h'://若为主机名
hostname=&argv[i][3];
break;
case 'n'://最多服务次数
maxservice=atoi(&argv[i][3]);
printf("maxservice: %d",maxservice);
break;
default:
userhelp();
break;
}
}
}
printf("port: %d\n",port);
printf("hostname: %s\n",hostname);
printf("maxservice: %d\n",maxservice);
return;
}
int initsockets()
{
WSADATA wsadata;
WORD sockversion;
int err;
sockversion=MAKEWORD(2,2);//设置winsock版本号
err=WSAStartup(sockversion,&wsadata);
if(err!=0)
{
printf("Error %d :Winsock not available\n",err);
return 1;
}
return 0;
}
void errorprint(char * x)
{
printf("Error %d : %s\n",WSAGetLastError(),x);
}
int loopcontrol(SOCKET listenfd, int ismultitasking)
{
SOCKET acceptfd;
struct sockaddr_in clientaddr;
int err;
int nsize;
int servernum=0;
HANDLE handles[MAX_SER];
int myID;
while(servernum<maxservice)//服务次数小于最大服务次数
{
nsize=sizeof(clientaddr);
acceptfd=accept(listenfd,(struct sockaddr*)&clientaddr,&nsize);//接受客户端请求
if(acceptfd==INVALID_SOCKET)//如果接收失败
{
errorprint("accept failed\n");
return 1;
}
printf("Accepted connectioin from client at %s\n",inet_ntoa(clientaddr.sin_addr));
if(ismultitasking)
{
handles[servernum]=CreateThread(NULL,1000,(LPTHREAD_START_ROUTINE)service,(LPVOID)acceptfd,0,&myID);//创建一个新线程来执行任务,新线程初始堆栈大小为1000,
}
else
service((LPVOID)acceptfd);
servernum++;
}
if(ismultitasking)
{
err=WaitForMultipleObjects(maxservice,handles,TRUE,INFINITE);//在一个线程中等待多个事件,当所有对象都被通知时函数才会返回,并且等待没有时间限制
printf("last thread to finish was thread #% d\n",err);
}
return 0;
}
void service(LPVOID lpv)
{
SOCKET acceptfd=(SOCKET) lpv;
const char *msg="HELLO CLIENT";
char reponse[4096];
memset(reponse,0,sizeof(reponse));//用0初始化数组
recv(acceptfd,reponse,sizeof(acceptfd),0);//接收数据存入reponse中
if(strcmp(reponse,"HELLO SERVER"))
{
printf("Application: client not using expected""protocol %s\n",reponse);
}
else
{
send(acceptfd,msg,strlen(msg)+1,0);//发送服务器端信息到客户端
}
closesocket(acceptfd);//关闭套接字
}
void userhelp()
{
printf("user help : -h:str -p:int -n:int\n");
printf(" -h:str The host name\n");
printf(" The default host is 127.0.0.1\n");
printf(" -p:int The Port number to use\n");
printf(" The default port is 9999\n");
printf(" -n:int The number of service,below MAX_SER\n");
printf(" The default number is 10");
ExitProcess(-1);
}
[code=C/C++][/code]
----------------------
麻烦稍详细解释一下 ...感激不尽!
[解决办法]
程序基本没得大问题,链接上不是因为在客户端这个地方.
memcpy((char*)&(serveraddr.sin_addr),ptrhost->h_addr_list,ptrhost->h_length);
这句构造链接信息结构体目标IP地址写法有问题,改成:
serveraddr.sin_addr.s_addr=inet_addr(hostname);
[解决办法]
//连接失败
if(err=INVALID_SOCKET)
==》
//连接失败
if(err==INVALID_SOCKET)