C语言版Socket通信原理附运行截图.docx
《C语言版Socket通信原理附运行截图.docx》由会员分享,可在线阅读,更多相关《C语言版Socket通信原理附运行截图.docx(9页珍藏版)》请在冰豆网上搜索。
C语言版Socket通信原理附运行截图
C语言版-Socket通信原理(附运行截图)
简单的客户/服务器程序设计与实现
实验目的及要求:
1、熟悉C编程环境。
2、熟悉Socket编程原理,掌握简单的套接字编程。
实验设备:
硬件:
PC机
软件:
CodeBlocks
实验内容及步骤:
什么是Socket?
Socket英文直译为“孔或插座”,也称为套接字。
用于描述IP地址和端口号,是一种进程间的通信机制。
你可以理解为IP地址确定了网内的唯一计算机,而端口号则指定了将消息发送给哪一个应用程序(大多应用程序启动时会主动绑定一个端口,如果不主动绑定,操作系统自动为其分配一个端口)。
Socket的类型
Stream:
一种流式Socket,针对于面向连接的TCP服务应用,安全,但效率低。
(本文重点)
Datagram:
数据报式的Socket,针对于无连接的UDP服务应用,不安全(丢失、顺序混乱,往往在接收端要分析完整性、重排、或要求重发),但效率高。
Socket程序一般应用模式及运行流程
服务器端会启动一个Socket,开始监听端口,监听客户端的连接信息,我们称之为WatchSocket。
客户端Socket连接服务器端的监听Socket,一旦成功连接,服务器端会立刻创建一个新的Socket负责与客户端进行通信,之后,客户端将不再与WatchSocket通信。
WatchSocket继续监听可能会来自其他客户端的连接。
上述过程就像是实现了一次三方会谈。
服务器端的Socket至少会有2个。
一个是WatchSocket,每成功接收到一个客户端的连接,便在服务器端创建一个通信Socket。
客户端Socket指定要连接的服务器端地址和端口,创建一个Socket对象来初始化一个到服务器的TCP连接。
编写用TCP协议实现的Client端和Server端程序并调试通过。
程序分两部分:
客户程序和服务器程序。
工作过程是:
服务器首先启动,它创建套接字之后等待客户的连接;客户启动后创建套接字,然后和服务器建立连接;建立连接后,客户接收键盘输入,然后将数据发送到服务器,服务器收到到数据后,将接收到的字符在屏幕上显示出来。
或者服务器接收键盘输入,然后将数据发送到客户机,客户机收到数据后,将接收到的字符在屏幕上显示出来。
服务器端代码:
#include
#pragmacomment(lib,"ws2_32")
#defineN20
structstu
{
charno[20];
charname[20];
}d[N];
intfd(char*stum,intn)
inti,j;
FILE*fp;
char*res="";
fp=fopen("D:
\\student.txt","r");
for(i=0;ifscanf(fp,"%s\t%s",&d[i].no,&d[i].name);fclose(fp);for(j=0;j{if(strcmp(d[j].no,stum)==0){res=d[j].name;break;}res="nothisstudent!";}returnres;}intstuno(){FILE*fp;fp=fopen("D:\\student.txt","r");inti=1;charc;while(!feof(fp)){while(c=='\n'){i++;break;}c=fgetc(fp);continue;}fclose(fp);returni;}intmain(){WSADATAwsaData;WSAStartup(MAKEWORD(2,2),&wsaData);SOCKETs=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);structsockaddr_insockaddr;sockaddr.sin_family=PF_INET;sockaddr.sin_addr.S_un.S_addr=inet_addr("192.168.1.118");sockaddr.sin_port=htons(8000);bind(s,(SOCKADDR*)&sockaddr,sizeof(SOCKADDR));listen(s,1);printf("listeningonport[%d].\n",8000);inti=stuno();printf("%d",i); while(TRUE){SOCKADDRclientAddr;intsize=sizeof(SOCKADDR);SOCKETclientsocket;clientsocket=accept(s,&clientAddr,&size);printf("***SYS***Newclienttouched.\n");char*msg="Hello,myclient.\r\n";send(clientsocket,msg,strlen(msg)+sizeof(char),NULL);printf("***SYS***HELLO.\n");while(TRUE){charbuffer[MAXBYTE]={0};recv(clientsocket,buffer,MAXBYTE,NULL);printf("***Client***%s\n",buffer);char*msg2=fd(buffer,i);send(clientsocket,msg2,strlen(msg)+sizeof(char),NULL);printf("***SYS***HELLO.\n");}closesocket(clientsocket);}closesocket(s);WSACleanup();return0;}(第一次运行不成功,需要修改如下设置:Settings->Compilersettings->otheroptions添加-std=c99LinerSettings->Linkersettings->addC:\软件\Codeblocks\MinGW\lib\libws2_32.a) 客户端代码:#include#include#include#pragmacomment(lib,"ws2_32")intmain(){Sleep(2000);WSADATAwsaData;WSAStartup(MAKEWORD(2,2),&wsaData);SOCKETs=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);structsockaddr_insockaddr;sockaddr.sin_family=PF_INET;sockaddr.sin_addr.S_un.S_addr=inet_addr("192.168.1.118");sockaddr.sin_port=htons(8000);connect(s,(SOCKADDR*)&sockaddr,sizeof(SOCKADDR));charbuffer[MAXBYTE]={0};recv(s,buffer,MAXBYTE,NULL);printf("***SERVER***%s",buffer);charszText[256];while(TRUE){gets(szText);szText[255]='\0';send(s,szText,strlen(szText),0);charbuffers[MAXBYTE]={0};recv(s,buffers,MAXBYTE,NULL);printf("***SERVER***%s\n",buffers);}closesocket(s);WSACleanup();getchar();exit(0);} 系统界面截图:本地ip:192.168.1.118服务端开启监听:客户端建立连接: 服务端的回复: 实验总结:socket()是用来创建一个,然后返回值是这个socket的描述符,很类似与文件描述符。bind()是用来为这个socket绑定server的IP+port地址,当然绑定之前要先对server的地址进行初始化。listen()的作用是监听client的请求,第二个参数规定了这个刚刚创建的socket可以接受几个client的服务请求。一旦accept()了一个client的请求,就获得了这个client的地址。操作系统就会又给它分配了一个socket,也就是accept的返回值,用来传输数据。也就是说,TCP开了2个socket,一个用来监听子进程,一个用来传输数accept之后就可以自由发挥,开始进行网络I/O了!
fscanf(fp,"%s\t%s",&d[i].no,&d[i].name);
fclose(fp);
for(j=0;j{if(strcmp(d[j].no,stum)==0){res=d[j].name;break;}res="nothisstudent!";}returnres;}intstuno(){FILE*fp;fp=fopen("D:\\student.txt","r");inti=1;charc;while(!feof(fp)){while(c=='\n'){i++;break;}c=fgetc(fp);continue;}fclose(fp);returni;}intmain(){WSADATAwsaData;WSAStartup(MAKEWORD(2,2),&wsaData);SOCKETs=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);structsockaddr_insockaddr;sockaddr.sin_family=PF_INET;sockaddr.sin_addr.S_un.S_addr=inet_addr("192.168.1.118");sockaddr.sin_port=htons(8000);bind(s,(SOCKADDR*)&sockaddr,sizeof(SOCKADDR));listen(s,1);printf("listeningonport[%d].\n",8000);inti=stuno();printf("%d",i); while(TRUE){SOCKADDRclientAddr;intsize=sizeof(SOCKADDR);SOCKETclientsocket;clientsocket=accept(s,&clientAddr,&size);printf("***SYS***Newclienttouched.\n");char*msg="Hello,myclient.\r\n";send(clientsocket,msg,strlen(msg)+sizeof(char),NULL);printf("***SYS***HELLO.\n");while(TRUE){charbuffer[MAXBYTE]={0};recv(clientsocket,buffer,MAXBYTE,NULL);printf("***Client***%s\n",buffer);char*msg2=fd(buffer,i);send(clientsocket,msg2,strlen(msg)+sizeof(char),NULL);printf("***SYS***HELLO.\n");}closesocket(clientsocket);}closesocket(s);WSACleanup();return0;}(第一次运行不成功,需要修改如下设置:Settings->Compilersettings->otheroptions添加-std=c99LinerSettings->Linkersettings->addC:\软件\Codeblocks\MinGW\lib\libws2_32.a) 客户端代码:#include#include#include#pragmacomment(lib,"ws2_32")intmain(){Sleep(2000);WSADATAwsaData;WSAStartup(MAKEWORD(2,2),&wsaData);SOCKETs=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);structsockaddr_insockaddr;sockaddr.sin_family=PF_INET;sockaddr.sin_addr.S_un.S_addr=inet_addr("192.168.1.118");sockaddr.sin_port=htons(8000);connect(s,(SOCKADDR*)&sockaddr,sizeof(SOCKADDR));charbuffer[MAXBYTE]={0};recv(s,buffer,MAXBYTE,NULL);printf("***SERVER***%s",buffer);charszText[256];while(TRUE){gets(szText);szText[255]='\0';send(s,szText,strlen(szText),0);charbuffers[MAXBYTE]={0};recv(s,buffers,MAXBYTE,NULL);printf("***SERVER***%s\n",buffers);}closesocket(s);WSACleanup();getchar();exit(0);} 系统界面截图:本地ip:192.168.1.118服务端开启监听:客户端建立连接: 服务端的回复: 实验总结:socket()是用来创建一个,然后返回值是这个socket的描述符,很类似与文件描述符。bind()是用来为这个socket绑定server的IP+port地址,当然绑定之前要先对server的地址进行初始化。listen()的作用是监听client的请求,第二个参数规定了这个刚刚创建的socket可以接受几个client的服务请求。一旦accept()了一个client的请求,就获得了这个client的地址。操作系统就会又给它分配了一个socket,也就是accept的返回值,用来传输数据。也就是说,TCP开了2个socket,一个用来监听子进程,一个用来传输数accept之后就可以自由发挥,开始进行网络I/O了!
if(strcmp(d[j].no,stum)==0)
{res=d[j].name;
break;}
res="nothisstudent!
";
}
returnres;
intstuno()
inti=1;
charc;
while(!
feof(fp)){
while(c=='\n')
i++;
break;
c=fgetc(fp);
continue;
returni;
intmain()
WSADATAwsaData;
WSAStartup(MAKEWORD(2,2),&wsaData);
SOCKETs=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
structsockaddr_insockaddr;
sockaddr.sin_family=PF_INET;
sockaddr.sin_addr.S_un.S_addr=inet_addr("192.168.1.118");
sockaddr.sin_port=htons(8000);
bind(s,(SOCKADDR*)&sockaddr,sizeof(SOCKADDR));
listen(s,1);
printf("listeningonport[%d].\n",8000);
inti=stuno();
printf("%d",i);
while(TRUE)
SOCKADDRclientAddr;
intsize=sizeof(SOCKADDR);
SOCKETclientsocket;
clientsocket=accept(s,&clientAddr,&size);
printf("***SYS***Newclienttouched.\n");
char*msg="Hello,myclient.\r\n";
send(clientsocket,msg,strlen(msg)+sizeof(char),NULL);
printf("***SYS***HELLO.\n");
charbuffer[MAXBYTE]={0};
recv(clientsocket,buffer,MAXBYTE,NULL);printf("***Client***%s\n",buffer);
char*msg2=fd(buffer,i);
send(clientsocket,msg2,strlen(msg)+sizeof(char),NULL);printf("***SYS***HELLO.\n");
closesocket(clientsocket);
closesocket(s);
WSACleanup();
return0;
(第一次运行不成功,需要修改如下设置:
Settings->Compilersettings->otheroptions添加-std=c99
LinerSettings->Linkersettings->addC:
\软件\Codeblocks\MinGW\lib\libws2_32.a
)
客户端代码:
Sleep(2000);
connect(s,(SOCKADDR*)&sockaddr,sizeof(SOCKADDR));
recv(s,buffer,MAXBYTE,NULL);
printf("***SERVER***%s",buffer);
charszText[256];
gets(szText);
szText[255]='\0';
send(s,szText,strlen(szText),0);
charbuffers[MAXBYTE]={0};
recv(s,buffers,MAXBYTE,NULL);
printf("***SERVER***%s\n",buffers);
getchar();
exit(0);
系统界面截图:
本地ip:
192.168.1.118
服务端开启监听:
客户端建立连接:
服务端的回复:
实验总结:
socket()是用来创建一个,然后返回值是这个socket的描述符,很类似与文件描述符。
bind()是用来为这个socket绑定server的IP+port地址,当然绑定之前要先对server的地址进行初始化。
listen()的作用是监听client的请求,第二个参数规定了这个刚刚创建的socket可以接受几个client的服务请求。
一旦accept()了一个client的请求,就获得了这个client的地址。
操作系统就会又给它分配了一个socket,也就是accept的返回值,用来传输数据。
也就是说,TCP开了2个socket,一个用来监听子进程,一个用来传输数accept之后就可以自由发挥,开始进行网络I/O了!
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1