实验目的
1、利用TCP实现套接字通信。
2、利用UDP实现套接字通信。
实验环境及准备
装有Linux系统的计算机。
实验原理
1、TCP/IP协议存在于OS中,网络服务通过OS提供。
2、应用程序要和操作系统交互,才能使用TCP/IP提供的网络通信功能。
3、交互的接口:即应用程序接口(API)。
4、从网络的观点看:TCP/IP和应用程序之间的接口。
实验内容
- 利用TCP实现套接字通信。
主要实现过程如下
TCP服务器代码:
serve.c
/******** 头文件 *********/
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <strings.h>
#include <stdlib.h>
#include <stdio.h>
/******** 宏定义 ********/
#define BUFFSIZE 100
int main()
{
int listenFd, connectFd;
socklen_t len;
int n;
struct sockaddr_in srcAddr, cliAddr;
char buf[BUFFSIZE];
//create socket
if((listenFd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket error");
exit(1);
}
bzero(&srcAddr, sizeof(srcAddr));
srcAddr.sin_family = AF_INET;
srcAddr.sin_port = htons(8888);
srcAddr.sin_addr.s_addr = htonl(INADDR_ANY);
//绑定套接字
if(bind(listenFd, (struct sockaddr*)&srcAddr, sizeof(srcAddr)) == -1)
{
perror("bind error");
exit(1);
}
//监听套接字
if(listen(listenFd, 5) == -1)
{
perror("listen error");
exit(1);
}
len = sizeof(cliAddr);
printf("listening ...\n");
while(1)
{
//从已完成队列中抓取一个套接字进行服务
if((connectFd = accept(listenFd, (struct sockaddr*)&cliAddr, &len)) == -1)
{
perror("accept error");
exit(1);
}
printf("accepted successful\n");
//从套接字中读取从客户端发来的数据
while((n = read(connectFd, buf, BUFFSIZE)) > 0)
{
if(buf[n] != '\0')
{
buf[n] = '\0';
}
printf("receive a message: %s", buf);
//将读取的数据写进套接字,发给客户端
if(write(connectFd, buf, n) < 0)
{
perror("write error");
exit(1);
}
}
}
//进程退出后,所有打开的文件描述符都会被关闭,因此打开的套接字文件也被关闭
return 0;
}
TCP客户端代码:
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
#include <strings.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
/******** 宏定义 *********/
#define BUFFSIZE 100
int main()
{
int sockFd;
int n;
struct sockaddr_in serverAddr;
char sendBuf[BUFFSIZE], recvBuf[BUFFSIZE];
//创建套接字
if((sockFd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket error");
exit(1);
}
bzero(&serverAddr, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(8888);
inet_pton(AF_INET, "192.168.225.132", &serverAddr.sin_addr);
//连接套接字
if(connect(sockFd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0)
{
perror("connect error");
exit(1);
}
//从标准输入中读取一行数据
while(fgets(sendBuf, BUFFSIZE, stdin) != NULL)
{
//将数据写入到套接字,发送给服务器
write(sockFd, sendBuf, strlen(sendBuf));
//从套接字中读取从服务器发来的数据
n = read(sockFd, recvBuf, BUFFSIZE);
//将接受到的数据写到标准输出中
write(STDIN_FILENO, recvBuf, n);
}
return 0;
}
实验结果
当运行服务器代码后出现listening ,接着运行客户端代码,发现连接成功,输入hello !!!后服务器输出收到的信息,再把收到的信息写到套接字里发回给客户端,所以看到了三个hello !!!。
利用UDP实现套接字通信。
UDP服务器代码:
serudp.c
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#define PORT 1234
#define MAXDATASIZE 100
int main()
{
int sockfd;
struct sockaddr_in server;
struct sockaddr_in client;
socklen_t addrlen;
int num;
char buf[MAXDATASIZE];
//创建套接字
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("Creatingsocket failed.");
exit(1);
}
bzero(&server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr= htonl (INADDR_ANY);
//绑定套接字
if(bind(sockfd, (struct sockaddr *)&server, sizeof(server)) == -1)
{
perror("Bind()error.");
exit(1);
}
addrlen=sizeof(client);
while(1)
{//接收从客户端来的信息
num =recvfrom(sockfd,buf,MAXDATASIZE,0,(struct sockaddr*)&client,&addrlen);
if (num < 0)
{
perror("recvfrom() error\n");
exit(1);
}
buf[num] = '\0';
printf("You got a message (%s) from client.\nIt's ip is%s, port is %d.\n",buf,inet_ntoa(client.sin_addr),htons(client.sin_port));
sendto(sockfd,"Welcometo my server.\n",22,0,(struct sockaddr *)&client,addrlen);
//当客户端发来bye跳出循环关闭套接字
if(!strcmp(buf,"bye"))
break;
}
close(sockfd);
}
UDP客户端代码
cliudp.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define PORT 1234
#define MAXDATASIZE 100
int main(int argc, char *argv[])
{
int sockfd, num;
char buf[MAXDATASIZE];
struct hostent *he;
struct sockaddr_in server,peer;
//当参数不符合格式给出提示
if (argc !=3)
{
printf("Usage: %s <IP Address><message>\n",argv[0]);
exit(1);
}
if ((he=gethostbyname(argv[1]))==NULL)
{
printf("gethostbyname()error\n");
exit(1);
}
//创建套接字
if ((sockfd=socket(AF_INET, SOCK_DGRAM,0))==-1)
{
printf("socket() error\n");
exit(1);
}
bzero(&server,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr= *((struct in_addr *)he->h_addr);
//发给服务器信息
sendto(sockfd, argv[2],strlen(argv[2]),0,(struct sockaddr *)&server,sizeof(server));
socklen_t addrlen;
addrlen=sizeof(server);
while (1)
{//从套接字接收信息到buf
if((num=recvfrom(sockfd,buf,MAXDATASIZE,0,(struct sockaddr *)&peer,&addrlen))== -1)
{
printf("recvfrom() error\n");
exit(1);
}
if (addrlen != sizeof(server) ||memcmp((const void *)&server, (const void *)&peer,addrlen) != 0)
{
printf("Receive message from otherserver.\n");
continue;
}
buf[num]='\0';
//输出buf的内容
printf("Server Message:%s\n",buf);
break;
}
close(sockfd);
}
UDP
编译服务器代码
当参数传输错误的时候提示格式
客户端传送hello给服务器
服务器收到hello信息, 并打印出服务器的ip和端口号