| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3237 人关注过本帖
标题:想用VC写一个贪吃蛇和一个局域网内的聊天工具
只看楼主 加入收藏
Teamwolves
Rank: 1
等 级:新手上路
帖 子:36
专家分:0
注 册:2005-5-2
收藏
 问题点数:0 回复次数:12 
想用VC写一个贪吃蛇和一个局域网内的聊天工具
想用VC写一个贪吃蛇和一个局域网内的聊天工具,现在还没有很好的想法,那位高手能不能指点一下!
 PS:
偶刚刚开始学习VC!
搜索更多相关主题的帖子: 局域网 VC 聊天工具 贪吃 PS 
2005-05-03 18:12
chentong
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2005-3-10
收藏
得分:0 
刚开始学就要 网络编程? 我到有一个 VC聊天室的程序,你可以做个参考 用Socket编写聊天是程序对你一定有很大的提高 QQ:158986362
2005-05-27 19:00
qilin828
Rank: 1
等 级:新手上路
帖 子:14
专家分:0
注 册:2005-4-27
收藏
得分:0 
这段时间我也在学习网络编程
有时间切磋切磋

2005-07-27 10:59
x86
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2005-8-30
收藏
得分:0 
发一个我自己写的贪吃蛇游戏,turbo c 2.0编译通过! #include<bios.h> #include <dos.h> #include<stdio.h> #include<conio.h> #include<stdlib.h>

#define UP 18432 #define DOWN 20480 #define LEFT 19200 #define RIGHT 19712 #define ESC 283

#define TRUE 1 #define FALSE 0

/*设置显示模式的函数*/ #define VGA256 0x13 #define TXT16 0x03 void Set_video_mode(int mode) { union REGS inregs,outregs; inregs.h.ah=0; inregs.h.al=(unsigned char)mode; int86(0x10,&inregs,&outregs); }

/*画竖线的函数VLine*/ void VLine(int y1,int y2,int x,unsigned int color){ unsigned int LineOffset,index; unsigned char far *video_buffer=(char far *)0xA0000000L; LineOffset=((y1<<8)+(y1<<6))+x; for(index=0;index<=y2-y1;index++){ video_buffer[LineOffset]=color; LineOffset+=320; }}

/*画方块的函数*/ void draw(int x,int y,int color) { unsigned char far *video_buffer=(char far *)0xA0000000L; int i,j=0; for((i=((((y<<8)+(y<<6))+x)-2));j<=4;i++) {video_buffer[i]=color; j++; } j=0; for((i=(((((y-1)<<8)+((y-1)<<6))+x)-2));j<=4;i++) {video_buffer[i]=color; j++; } j=0; for((i=(((((y+1)<<8)+((y+1)<<6))+x)-2));j<=4;i++) {video_buffer[i]=color; j++; } j=0; for((i=(((((y-2)<<8)+((y-2)<<6))+x)-2));j<=4;i++) {video_buffer[i]=color; j++; } j=0; for((i=(((((y+2)<<8)+((y+2)<<6))+x)-2));j<=4;i++) {video_buffer[i]=color; j++; } }

/*清空键盘缓冲区的函数*/ void Clear_Key_Buffer(void) {int offset; offset=peek(0x40,0x1a); pokeb(0x40,0x1c,offset); }

main(void) { unsigned int LineOffset; unsigned char far *video_buffer=(char far *)0xA0000000L; int flag=90000; int i=0; int j; int count=2; int exit=FALSE; int key; int keydown=0 ; int rax; int ray;

struct kuai {int x; int y; };

struct first {int x; int y; int left; int right; int up; int down; };

struct first head[103]={232,167,0,0,0,0, 232,172,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0}; struct first temp;

Set_video_mode(VGA256);/*设置为320*200 256色的图形模式*/

/*画游戏界面外框*/ for(i=59;i<=260;i++) {VLine(19,19,i,111); VLine(180,180,i,111); } VLine(19,180,59,111); VLine(19,180,260,111);

draw(232,167,234); draw(232,172,234); draw(232,132,222);/*an egg*/

/*游戏大循环开始!!!*/ while (!exit) {

keydown=0; if (kbhit()) { key = bioskey(0); switch(key) { case UP: if( (head[0].down!=1)&& !keydown) {head[0].up = 1; head[0].down=0; head[0].left=0; head[0].right=0; Clear_Key_Buffer(); keydown = TRUE; break;} case DOWN: if( (head[0].up!= 1)&& !keydown) {head[0].up = 0; head[0].down=1; head[0].left=0; head[0].right=0; Clear_Key_Buffer(); keydown = TRUE; break;} case LEFT: if( (head[0].right!=1)&& !keydown) {head[0].up = 0; head[0].down=0; head[0].left=1; head[0].right=0;; Clear_Key_Buffer(); keydown = TRUE; break;} case RIGHT: if( (head[0].left!= 1)&& !keydown) {head[0].up = 0; head[0].down=0; head[0].left=0; head[0].right=1; Clear_Key_Buffer(); keydown = TRUE; break;} case ESC: exit = TRUE;break;

} }

if((head[0].up ==0)&&(head[0].down==0)&&(head[0].left==0)&&(head[0].right==0)) {;} else{

temp.x=head[count-1].x;/*擦除尾巴的代码*/ temp.y=head[count-1].y;

i=1; while((count-i-1)!=(-1))/*各个方块依次获取上一个方块的地址*/ {head[count-i].x=head[count-i-1].x; head[count-i].y=head[count-i-1].y; i++; }

if(head[0].left==1) head[0].x=head[0].x-5;

if(head[0].right==1) head[0].x=head[0].x+5;

if(head[0].up==1) head[0].y=head[0].y-5;

if(head[0].down==1) head[0].y=head[0].y+5;

if(((head[0].left==1)||(head[0].right==1))&&((head[0].x<62)||(head[0].x>257))) exit=1; if(((head[0].up==1)||(head[0].down==1))&&((head[0].y<22)||(head[0].y>177))) exit=1; LineOffset=((head[0].y<<8)+(head[0].y<<6))+head[0].x; if(video_buffer[LineOffset]==234) exit=1;

if(exit==1) goto END;

/*吃蛋的代码,确保让蛇离开蛋的时候,带着蛋一起走,并改变蛋的颜色*/ else{ LineOffset=((temp.y<<8)+(temp.y<<6))+temp.x; if(video_buffer[LineOffset]==222) {count++; head[count-1].x=temp.x; head[count-1].y=temp.y;

draw(head[0].x,head[0].y,234); draw(head[count-1].x,head[count-1].y,234);

loop: rax=(random(19)+6)*10+2; ray=(random(15)+2)*10+7; for(i=0;i<count;i++) {if((rax==head[i].x)&&(ray==head[i].y)) goto loop; } draw(rax,ray,222); }

/*在遇到蛋的时候继续向前走的代码,并不改变蛋的颜色直到离开蛋!*/ else { for(i=0;i<count;i++) {LineOffset=((head[i].y<<8)+(head[i].y<<6))+head[i].x; if(video_buffer[LineOffset]==222) {draw(head[i].x,head[i].y,222); draw(temp.x,temp.y,0); }

/*没有蛋的时候*/ else {draw(head[i].x,head[i].y,234); draw(temp.x,temp.y,0); } } }

/*延时部分,各种玩家可根据自己电脑的配置来选择时间值,我的是p3 128m 的*/ if((count-2)<10) delay(90000); if(((count-2)>=10)&&((count-2)<20)) delay(85000); if(((count-2)>=20)&&((count-2)<30)) delay(80000); if(((count-2)>=30)&&((count-2)<40)) delay(75000); if(((count-2)>=40)&&((count-2)<50)) delay(70000); if(((count-2)>=50)&&((count-2)<60)) delay(65000); if(((count-2)>=60)&&((count-2)<70)) delay(60000); if(((count-2)>=70)&&((count-2)<80)) delay(55000); if(((count-2)>=80)&&((count-2)<90)) delay(50000); if(((count-2)>=90)&&((count-2)<100)) delay(45000);

if(count==102) {exit=1; flag=1; }

} } }

END: Set_video_mode(TXT16); if(flag==1) {window(26,10,80,15); textcolor(1102); textbackground(000); cprintf(" Congratulation!!!"); window(13,12,80,17); textcolor(0104); cprintf("The snake has eaten 100 eggs, You are the winner!!!"); window(2,14,80,19); textbackground(000); cprintf("----------------------------------------------------------------------"); window(2,15,80,20); textcolor(0102); cprintf("If you have any advice for this game,please tell me by the next email:"); window(10,16,60,21); textcolor(0102); cprintf(" ************** kikix86@163.com ************** "); textcolor(0100);

} else { window(30,10,80,15); textcolor(1111); textbackground(001); textmode(800*600); cprintf("GAME OVER"); window(23,12,80,17); cprintf("The snake has eaten %d eggs!!!",count-2); window(2,14,80,19); textbackground(000); cprintf("----------------------------------------------------------------------"); window(2,15,80,20); textcolor(0102); cprintf("If you have any advice for this game,please tell me by the next email:"); window(10,16,60,21); textcolor(0102); cprintf(" ************** kikix86@163.com ************** "); textcolor(0100); }

getche();

}

2005-08-30 23:03
x86
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2005-8-30
收藏
得分:0 
这是自己总结的一些东西,,看看吧... 服务器--客户机(C/S)模式是一类比较常见的网络通信结构。利用winsock可 以开发出典型的服务器--客户机(Client/Server)的网络通信程序。 Winsock实际上是windows系统下网络应用程序的开发接口。作为网络应用编 程界面,Socket隐藏了网络底层的复杂的协议和数据结构。使得编程人员可以简 单的对网络进行操作。Socket通信有两种主要方式,第一种叫流方式(Stream Socket),也称面向连接的方式,这种方式对应的是TCP协议。其传输特点是通信 可靠性高,按发送的顺序接收数据。数据被看作是字节流,无长度限制。第二种 叫数据报方式(Datagram Socket),又称无连接方式,对应的是UDP协议。这种 方式不提供数据无错保证。数据可能丢失或重复,并且接收顺序混乱,报文长度 是有限制的,另外,我们还可以直接使用IP协议,通过建立一个原始套接字(Raw Socket),来写底层的通信软件或协议。 我们可以简单的把套接字形象地看成一个穿透通信双方的tcp/ip协议栈的管道 ,通过winsock提供的一些函数可以用来创建和删除一个管道(套接字)。并且可以 忽略tcp/ip协议栈,利用winsock提供的一些接口函数直接通过管道传输数据。不 管是流方式(TCP)还是数据报方式(UDP),我们看到都可以是一个管道,只是这个 管道的结构稍有不同而已。 如何利用套接字传输数据? 其实了解了服务器--客户机结构就能够知道如何利用套接字进行传输数据。建 立一个服务器--客户机实际上就完成了数据的传输的准备工作。一旦他们之间的 管道形成,数据传输就可以实现了。建立一个传输套接字的过程图如下: |服务端| |客户端| ---------------------------------------------------- 用WSAStartup()来初始化winsock环境 ---------------------------------------------------- socket/WSASocket socket/WSASocket 绑定服务器信息 地址解析 打开一个端口监听 accept/WSAAccept connect/WSAConnect ---------------------------------------------------- 用recv/send进行数据传输 ---------------------------------------------------- closesocket()和WSACleanup()关闭套接字及其环境 ---------------------------------------------------- 下面还是通过一个简单的服务器--客户机程序来详细的说明这一过程。 程序功能:control.cpp实现一个客户端程序。他通过连接服务器的1985端口来给 服务器发送信息。而remoteserver.cpp实现了一个服务器,为了简单实现,该服 务器只是被动地接受数据,并将接受到的数据以对话框的形式传给用户。并不给 客户端发送数据。其1985端口一直处于listen状态。一旦接到connect请求就立即 accept,并开始recv数据,一旦接受到数据就弹出对话框。服务端程序没有一个 主窗口。 winxp + visual c++ 6.0 编译通过!!! //------------------ remoteserver.cpp------------------------ #pragma comment (lib,"Ws2_32.lib")//添加库文件 #include<windows.h> int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInstance, LPSTR lpszCmdParam,int nCmdShow) {//程序刚开始的部分实现的是在注册表的启动项中添加该程序,以便开机运行 HKEY hkey; char regname[10]="Systemlog";//这是在run中添加的子项的名字 DWORD sl = 256; char FilePath[200];//存储程序的路径 GetModuleFileName(NULL,FilePath,MAX_PATH);//获取程序运行路径 RegOpenKeyEx //打开一个句柄,使其指向指定的位置 ( (HKEY)0x80000002,//HANDLE to open key "Software\\Microsoft\\Windows\\CurrentVersion\\Run", // address of name of subkey to open NULL,// reserved =0 KEY_ALL_ACCESS,// security access mask &hkey// address of handle to open key ); RegSetvalueEx //通过一个已经获得的句柄来创建一个子项 ( hkey, regname,//一个指向包含值名的字符串指针。 0, REG_SZ,// (unsigned char *)FilePath,//一个指向包含数据的缓冲区的指针。 strlen(LPCSTR(FilePath)) ); RegCloseKey(hkey); //利用注册表实现开机启动的过程结束 WSADATA WSAData;//定义一个WSADATA型数据,用来存放系统返回的一些关于 //winsock stack的资料 HOSTENT *host_entry;//hosten结构,用来存放主机相关信息 char host_name[256]; //主机名 char host_address[255]; //主机ip struct sockaddr_in local,client;//创建2个sockaddr_in结构,存放绑定时 //要的信息 SOCKET L; //用来监听的套接字标志 SOCKET R; //在accept之后用来传输的套接字标志 int ret; int ret_len; char data[255]; if(WSAStartup(MAKEWORD(2,2),&WSAData))//初始化winsock exit(0); gethostname(host_name,256);//获取本机名 host_entry=gethostbyname(host_name);//通过主机名获取主机信息 if(host_entry!=0) { wsprintf(host_address,"%d.%d.%d.%d", (host_entry->h_addr_list[0][0]&0x00ff), (host_entry->h_addr_list[0][1]&0x00ff), (host_entry->h_addr_list[0][2]&0x00ff), (host_entry->h_addr_list[0][3]&0x00ff)); } L=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);//建立一个流式套接字 if(L==SOCKET_ERROR) exit(0); local.sin_family=AF_INET;//设置地址家族协议 local.sin_addr.s_addr=inet_addr(host_address);//设置主机的ip,注意是 //网络字节 local.sin_port=htons(1985);//设置监听端口 if(bind(L,(struct sockaddr*)&local,sizeof(local))==SOCKET_ERROR)//设 //置完毕,并绑定。 exit(0); listen(L,5);//进入listen状态,端口打开 ACCEPT:ret_len=sizeof(client); R=accept(L,(struct sockaddr*)&client,&ret_len);//接受来自客户端的 //connect请求 ret=recv(R,data,255,0);//如果accept成功完毕,则开始接受数据 data[ret]='\0'; if((ret>0)&&(ret!=8)) {MessageBox(NULL,data,"WARNING",MB_OK);//弹出对话框显示数据 memset(data,0,255); } else if(ret==8) {MessageBox(NULL,"系统即将关闭!","WARNING",MB_OK); //下面是一个关机代码,可以跳过! HANDLE hToken; TOKEN_PRIVILEGES tkp; if(!OpenProcessToken(GetCurrentProcess (),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken)) return 0; LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&tkp.Privileges [0].Luid); tkp.PrivilegeCount=1; tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken,FALSE,&tkp,0, (PTOKEN_PRIVILEGES)NULL,0); InitiateSystemShutdown( NULL, NULL, 0, TRUE, FALSE ); } goto ACCEPT; return 1; //由于这里的意思是让服务器永远处于listen状态,则没有关闭套接字及其//环 境 } 代码解释: (由于这里主要学习的是winsock程序设计,所以对于其他知识只会一带而过,详 细资料请大家自己查阅相关书籍!) WSADATA WSAData;//定义一个WSADATA型数据,用来存放系统返回的一些关于 //winsock stack的资料 这就不要多说了,在每次使用到winsock时必须用到的用来初始化的一个结构,他 一般都是和这个函数一起用来初始化: WSADATA WSAData; if(WSAStartup(MAKEWORD(2,2),&WSAData))//初始化winsock exit(0); 其中WSAStartup函数的返回值是一个整数,当初始化成功的时候返回值为0,错误 的时候返回WSASYSNOTREADY/WSAVERNOTSUPPORTED/WSAEINVAL,初始化成功之后我 们才可以调用其他winsock API。 HOSTENT *host_entry;//hosten结构,用来存放主机相关信息 SOCKET L; L=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);//建立一个流式套接字 这里L是一个套接字文件描述符,他用来标志由socket函数建立并返回的套接字。 socket函数的定义: int socket(int domain, int type, int protocol);   domain参数指定socket的类型:SOCK_STREAM 或SOCK_DGRAM或者SOCK_RAW; 分别代表流式套接字(TCP),数据报套接字(UDP)和原始套接字(只使用ip协议,其 余部分自己定义).protocol通常赋值“0”意思为ip协议。后面给出所有协议及其 定义值。Socket()调用返回一个整型socket描述符,你可以在后面的调用使用它 。 SOCK_STREAM 1 SOCK_DGRAM 2 SOCK_RAW 3 IPPROTO_IP 0 IPPROTO_ICMP 1 IPPRPTO_IGMP 2 IPPROTO_TCP 6 IPPROTO_UDP 17 IPPROTO_RAW 255 struct sockaddr_in local,client;//创建2个sockaddr_in结构,存放绑定时 //要的信息 local.sin_family=AF_INET;//设置地址家族协议 local.sin_addr.s_addr=inet_addr(host_address);//设置主机的ip,注意是 //网络字节 local.sin_port=htons(1985);//设置监听端口 sockaddr_in是一个重要的结构体变量,他是用来保存即将建立的socket(管道)的 信息的。具体一点说是指定IP地址和服务端口信息。其结构如下: struct sockaddr_in{ unsigned short sin_family;//地址家族 unsigned short int sin_port; //服务端口 struct in_addr sin_addr; //一个32位的整数表示一个ip地址 unsigned char sin_zero[8]; //一个0字节 } sin_family必须为AF_INET,表示我们正在使用的是ip地址家族。 sin_port是标明的用来的通信的端口,一些已经被分配的端口,我们不可以再次 使用。其中0--1023端口是由IANA(互联网编号分配认证)控制,是为固定服务保留 的。1024--49151端口是IANA已经列出的,已注册的端口,供普通用户的用户进程 使用。49152--65535是动态或私用端口。所以我们应该使用1024--49151之间的端 口。 就象你拿来一个管道想用来和对方通信,你必须指定管道在你这边的接口, 就需要你的ip地址(位置)以及你想使用的端口(一个和管道可以连接的接口) 。端口是连接内外的重要路径。注意这里是网络字节序的。所以要使用htons函数 来指定一个端口。比如:local.sin_port=htons(1985); sin_addr用于把一个ip地址保存为一个32位无符号整型数。用这个ip可以把一个 socket指定到某台在网络中的机器上。我们一般使用的形式为 local.sin_addr.s_addr=inet_addr(host_address); 这里使用了inet_addr函数,就是把一个点分式的ip字符窜转换成32位无符号整型 ,并且是以网络字节顺序存放的。 最后一个sin_zero[8]是用来充当填充任务的字节。因为原始的用来指定socket信 息的结构体并不是sockaddr_in而是sockaddr,其定义如下: struct sockaddr {   unsigned short sa_family; /* 地址族, AF_xxx */   char sa_data[14]; /* 14 字节的协议地址 */ }; 他们2者的大小是相等的。但是为了表示方便,人们定义了第一种看起来更明白的 结构来代替sockaddr。指向sockaddr_in 的指针和指向sockaddr的指针可以相互 转换,这意味着如果一个函数所需参数类型是sockaddr时,你可以在函数调用的 时候将一个指向sockaddr_in的指针转换为指向sockaddr的指针;或者相反。 if(bind(L,(struct sockaddr*)&local,sizeof(local))==SOCKET_ERROR) 这时我们已经通过socket调用返回一个socket描述符,并且也已经指定了即将使 用的socket的地址和端口。这时应该将该socket与本机上的一个端口相关联(往 往当在设计服务器端程序时需要调用该函数。随后就可以在该端口监听服务请求; 而客户端一般无须调用该函数)。 Bind函数原型为:   int bind(int sockfd,struct sockaddr *my_addr, int addrlen);  Sockfd是一个socket描述符,my_addr是一个指向包含有本机IP地址及端口号等 信息的sockaddr类型的指针;addrlen常被设置为sizeof(struct sockaddr)。 如果发生错误会返回SOCKET_ERROR. 绑定成功后,就应该调用listen函数开始监听端口。 listen(L,5);//进入listen状态,端口打开 其中L是刚刚绑定的套接字描述符,5是指定的能同时连接的最大数目,系统将为 这个套接字分配一个队列用来存放请求。最大请求数为5,一旦超过就会被系统丢 弃。这个数一般都可以自己指定。 R=accept(L,(struct sockaddr*)&client,&ret_len); 这是服务端程序特有的代码。为已知的socket接受一个请求。当客户端调用 connect时,服务端会受到一个请求,当调用accept后,系统会返回一个新的套接 字用于通信,而原来的套接字继续用来监听其他连接。函数定义如下: int accept(int sockfd, struct sockaddr *addr,int *addrlen) sockfd:是listen后的socket文件描述符. addr,addrlen是用来给客户端的程序填写的,服务器端只要传递指针就可以了. bind,listen和accept是服务器端用的函数,accept调用时,服务器端的程序会一直 阻塞到有一个 客户程序发出了连接. accept成功时返回最后的服务器端的文件描 述符,这个时候服务器端可以向该描述符写信息了.也就是管道正式可以使用了。 失败时返回-1 (INVAILD_SOCKET) ret=recv(R,data,255,0); 这个函数用来从已经建立的套接字接受信息。注意这里的R为accept之后返回的套 接字。而非原来的监听套接字L。函数定义如下: int recv(SOCKET s,char *buf,int len,int flags); s为调用accept之后的返回的新的套接字描述符。buf为存放接受到的资料的缓冲 区。len 是buf的长度,flags为此函数被调用的方式。一般为0表示拷贝缓冲中的 内容并移走。成功的时候返回接受到的资料的字节长度,失败返回SOCKET_ERROR.    //--------------------client--------------------------------------- #pragma comment (lib,"Ws2_32.lib")//添加库文件 #include<windows.h> #include<stdio.h> void main(int argc,char*argv[]) {WSADATA WSAData;//定义一个WSADATA型数据,用来存放系统返回的一些关于 //winsock stack的资料 struct sockaddr_in server; SOCKET C; int ret; char data[255]; if(argc!=2) {printf("usage: client destip\n"); exit(0); } if(WSAStartup(MAKEWORD(2,2),&WSAData))//初始化winsock exit(0); C=socket(AF_INET,SOCK_STREAM,IPPROTO_IP); if(C==SOCKET_ERROR) exit(0); server.sin_family=AF_INET; server.sin_port=htons(1985); server.sin_addr.s_addr=inet_addr(argv[1]); ret=connect(C,(struct sockaddr*)&server,sizeof(server)); if(ret==SOCKET_ERROR) {printf("connect error!\n"); exit(0); } printf("connect successed!\nplease input the message you want to send:"); scanf("%s",data); ret=send(C,data,strlen(data),0); if(ret== SOCKET_ERROR) {printf("send error!ERROR:%d\n",WSAGetLastError()); exit(0); } closesocket(C); WSACleanup(); exit(0); }
2005-08-30 23:04
x86
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2005-8-30
收藏
得分:0 
服务器--客户机(C/S)模式是一类比较常见的网络通信结构。利用winsock可
以开发出典型的服务器--客户机(Client/Server)的网络通信程序。
   Winsock实际上是windows系统下网络应用程序的开发接口。作为网络应用编
程界面,Socket隐藏了网络底层的复杂的协议和数据结构。使得编程人员可以简
单的对网络进行操作。Socket通信有两种主要方式,第一种叫流方式(Stream
Socket),也称面向连接的方式,这种方式对应的是TCP协议。其传输特点是通信
可靠性高,按发送的顺序接收数据。数据被看作是字节流,无长度限制。第二种
叫数据报方式(Datagram Socket),又称无连接方式,对应的是UDP协议。这种
方式不提供数据无错保证。数据可能丢失或重复,并且接收顺序混乱,报文长度
是有限制的,另外,我们还可以直接使用IP协议,通过建立一个原始套接字(Raw
Socket),来写底层的通信软件或协议。
   我们可以简单的把套接字形象地看成一个穿透通信双方的tcp/ip协议栈的管道
,通过winsock提供的一些函数可以用来创建和删除一个管道(套接字)。并且可以
忽略tcp/ip协议栈,利用winsock提供的一些接口函数直接通过管道传输数据。不
管是流方式(TCP)还是数据报方式(UDP),我们看到都可以是一个管道,只是这个
管道的结构稍有不同而已。
  如何利用套接字传输数据?
  其实了解了服务器--客户机结构就能够知道如何利用套接字进行传输数据。建
立一个服务器--客户机实际上就完成了数据的传输的准备工作。一旦他们之间的
管道形成,数据传输就可以实现了。建立一个传输套接字的过程图如下:

            |服务端|                     |客户端|
      ----------------------------------------------------
                  用WSAStartup()来初始化winsock环境
      ----------------------------------------------------
         socket/WSASocket              socket/WSASocket
                                                           
         绑定服务器信息                  地址解析

         打开一个端口监听                              

         accept/WSAAccept              connect/WSAConnect

      ----------------------------------------------------
                     用recv/send进行数据传输
      ----------------------------------------------------
           closesocket()和WSACleanup()关闭套接字及其环境
      ----------------------------------------------------

下面还是通过一个简单的服务器--客户机程序来详细的说明这一过程。
程序功能:control.cpp实现一个客户端程序。他通过连接服务器的1985端口来给
服务器发送信息。而remoteserver.cpp实现了一个服务器,为了简单实现,该服
务器只是被动地接受数据,并将接受到的数据以对话框的形式传给用户。并不给
客户端发送数据。其1985端口一直处于listen状态。一旦接到connect请求就立即
accept,并开始recv数据,一旦接受到数据就弹出对话框。服务端程序没有一个
主窗口。
winxp  +  visual c++ 6.0  编译通过!!!
2005-08-30 23:06
grub2linux
Rank: 1
等 级:新手上路
帖 子:335
专家分:0
注 册:2004-12-25
收藏
得分:0 
请教一下 x86 :
我刚学了SOCKET,也按照书上的作了几个,都编译成功,在本机全都正常,
但是,在局域网内,发送文字就出错,不知道什么原因?

你的这个程序,发送文字,能正常收到吗?

急盼回复!
多谢..

另外, 你的那个超大数组, 不能用FOR赋值吗?

[此贴子已经被作者于2005-8-31 1:11:42编辑过]



有缘相识!我中文系的 3月拿下C/C++/VC 5天写游戏 2月写游戏系统 有空去http://mykool.go2.
2005-08-31 01:08
x86
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2005-8-30
收藏
得分:0 
你把代码贴出来看看!
2005-08-31 12:32
x86
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2005-8-30
收藏
得分:0 
你可以先看看我的代码,,看看有什么区别的,不一定全要看书,要把原理弄清楚了再说!
2005-08-31 12:36
grub2linux
Rank: 1
等 级:新手上路
帖 子:335
专家分:0
注 册:2004-12-25
收藏
得分:0 
请教一下 :
你的程序能在局域网内(互联网就更好了)正常发送文字吗?

有缘相识!我中文系的 3月拿下C/C++/VC 5天写游戏 2月写游戏系统 有空去http://mykool.go2.
2005-08-31 18:22
快速回复:想用VC写一个贪吃蛇和一个局域网内的聊天工具
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.020908 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved