首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

建立TCP/IP连接,该如何解决

2012-05-23 
建立TCP/IP连接刚接触这部分内容 照着书做的 大致了解了一下 但是程序运行的时候服务器端始终无法收到用户

建立TCP/IP连接
刚接触这部分内容 照着书做的 大致了解了一下 但是程序运行的时候服务器端始终无法收到用户端的请求 劳烦老手帮忙看一下 稍加讲解.... 感谢!

这是用户端

C/C++ code
#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);}

// TCP.c.cpp : 定义控制台应用程序的入口点。
//
#include<stdio.h>
#pragma comment(lib,"wsock32.lib")
#include<WinSock2.h>

#define MAX_SER 10

char *hostname;
unsigned short maxservice;
unsigned short port;

void initial();//系统初始化(主机名、最大服务进程数、端口号)
int initsockets();
void getargments(int argc,char** argv);//获取用户提供的选项
void errorprint(char * x);
void userhelp();
int loopcontrol(SOCKET listenfd,int ismultitasking);
void service(LPVOID lpv);





int main(int argc,char**argv)
{
SOCKET listenfd;
int err;
struct sockaddr_in serveraddr;
struct hostent *ptrhost;

initial();//初始化系统

getargments(argc,argv);//获取参数
initsockets();//初始化socket




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)

热点排行