大四下修TCPIP課程,第一項作業為 寫一個關於socket的程式,參考http://www.powercam.cc/show.php?id=218 而修改出如下的code,
作業環境:win7 32bit
Compiler: VC++ 2010
以下為Server端:code
/////////////////////////////////////////////////////////
#ifndef _WINSOCK2API_
#endif
// Prevent inclusion of winsock.h
#ifdef _WINSOCKAPI_
#endif
// NOTE: If you use Windows Platform SDK, you should enable following definition:
// #define USING_WIN_PSDK
#if !defined(WIN32_LEAN_AND_MEAN) && (_WIN32_WINNT >= 0x0400) && !defined(USING_WIN_PSDK)
#include <windows.h>
#else
#include <winsock2.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#pragma comment (lib, "WS2_32.lib ")
//#pragma comment(lib, "winsock.lib")
#define MAXLINE 1024 //buffer line
void main()
{
SOCKET serv_sd,cli_sd;
int cli_len,n;
char str[MAXLINE];
struct sockaddr_in serv,cli;
WSADATA wsadata;
if(WSAStartup(0x101,(LPWSADATA) &wsadata) !=0 ) //要使用winsock API 必須先statrup
{
fprintf (stderr,"echo_serv:can;t use winsockDLL\n");
exit(1);
}
if ( (serv_sd = socket (AF_INET,SOCK_STREAM,0) ) == SOCKET_ERROR)
{
fprintf (stderr,"echo_serv:can't open TCP socket\n");
exit(1);
}
/////以上在建立socket
//以下在填入winsock struct 資訊
serv.sin_family =AF_INET;
serv.sin_addr.s_addr =0; //0 為無強制server ip 給 winsock 決定
serv.sin_port =htons(IPPORT_ECHO); //指定IPPort_echo 為echo port
//以下定義protocal
if (bind (serv_sd,(LPSOCKADDR)&serv,sizeof(serv))<0)
{
fprintf(stderr,"echo_serv :can't bind local address\n");
exit(1);
}
//以下為最多可以listen 5個request
if( listen (serv_sd,5)<0)
{
fprintf(stderr,"echo_serv:listen() error\n");
exit(1);
}
//以下為傳送接收
cli_len = sizeof(cli);
while(1)
{
printf("echo_serv:waiting for client\n");
cli_sd=accept(serv_sd,(struct sockaddr *)&cli,&cli_len);//建立與client的連線
if(cli_sd==SOCKET_ERROR)
{
fprintf(stderr,"echo_serv:accept() error\n");
closesocket(cli_sd);
}
else
{
while(1)
{
if( (n=recv(cli_sd,str,MAXLINE,0)) ==0)
{
fprintf(stderr,"echo_serv:connection closed\n");
break;
}else if (n==SOCKET_ERROR)
{
fprintf (stderr,"echo_serv:recv() error \n");
break;
}
str[n]='\0';
printf("echo_serv:%s",str); //顯示從client 傳來的字串
if(send(cli_sd,str,strlen(str),0) == SOCKET_ERROR)
{
fprintf(stderr,"echo_serv:connection closed\n");
break;
}
}//while
}//if
}
//結束 winsock DLL
closesocket(serv_sd);
closesocket(cli_sd);
WSACleanup();
}//main
/////////////////////////////////////////////////////////////////server端code結束
//////////////////////////////////////////////////////////////以下為client端
#ifndef _WINSOCK2API_
#endif
// Prevent inclusion of winsock.h
#ifdef _WINSOCKAPI_
#endif
// NOTE: If you use Windows Platform SDK, you should enable following definition:
// #define USING_WIN_PSDK
#if !defined(WIN32_LEAN_AND_MEAN) && (_WIN32_WINNT >= 0x0400) && !defined(USING_WIN_PSDK)
#include <windows.h>
#else
#include <winsock2.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#pragma comment (lib, "WS2_32.lib ")
//#pragma comment(lib, "winsock.lib")
#define MAXLINE 1024 //buffer line
void main()
{
SOCKET sd; //socket 描述子
int n;
char str[MAXLINE];
struct sockaddr_in serv;
WSADATA wsadata;
if(WSAStartup(0x101,(LPWSADATA) &wsadata) !=0 ) //要使用winsock API 必須先statrup
{
fprintf (stderr,"echo_serv:WSAStartup() fails\n");
exit(1);
}
printf("Please keyin server IP: "); //輸入目標server的IP
fgets(str,MAXLINE,stdin);
serv.sin_family =AF_INET; //family = IPv4
serv.sin_addr.s_addr =inet_addr(str); //IP 為剛剛輸入的
serv.sin_port =htons(IPPORT_ECHO); //指定IPPort_echo 為echo port
//開啟TCP socket
if( (sd=socket(AF_INET,SOCK_STREAM,0)) == SOCKET_ERROR)
{
fprintf(stderr,"echo_cli:can't open tcp socket\n");
exit(1);
}
//try to connect server
if(connect(sd,(LPSOCKADDR) &serv,sizeof(serv)))
{
fprintf (stderr,"echo_cli:can't connect to server\n");
exit(1);
}
while(fgets(str,MAXLINE,stdin) !=NULL) //要求使用者keyin字串
{
if(send(sd,str,strlen(str)+1,0) == SOCKET_ERROR) //傳送字串看有無錯誤
{
fprintf(stderr,"echo_cli:send() error! \n");
break;
}
if ( (n=recv(sd,str,MAXLINE,0)) == 0)
{
fprintf(stderr,"echo_cli:connection closed\n");
break;
}else if(n==SOCKET_ERROR)
{
fprintf(stderr,"echo_cli:recv() error!\n");
break;
}
else printf(str); //若收回來也無錯誤則Print
}
closesocket(sd);
WSACleanup();
}//main
/////////////////////////////////////////////////////
備忘:對於原影片作者中的include各項會無法載入"winsock.h"所以上網查了許多的資料,最後用了上述的define方法終於解決了否則會顯示"無法辨析的外部符號.........."
但是上述code只能一個server對應一個client,若有其他client同時進入,則必須排隊在外等待,若要做到類似聊天室的功能,可能需要增加thread來監聽其他client,有待改進
2012.3.18 ED
沒有留言:
張貼留言