一、实验目的
1、了解网络编程概念,了解套接字编程相关技术;
2、掌握socket编程相关函数功能,使用方法;
3、掌握socket编程基本流程及方法。
二、实验环境:
一台运行GNOME图形用户界面的任意一种Linux操作系统的计算机。
PART 1 程序理解 (socket实现服务器端-客户端的TCP通信)
- 建立一个服务器端程序server.c,代码如下:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define SERVER_PORT 6000 //端口号可自己设置
#define SERVER_IP "192.168.126.128" // IP 地址请自己根据实际情况设置
int listen_fd = -1;
void signal_handler(int arg)
{
printf("close listen_fd(signal = %d)\n", arg);
close(listen_fd);
exit(0);
}
int main(int argc, const char *argv[])
{
int new_fd = -1;
struct sockaddr_in server;
struct sockaddr_in client;
socklen_t saddrlen = sizeof(server);
socklen_t caddrlen = sizeof(client);
signal(SIGINT, signal_handler);
memset(&server, 0, sizeof(server));
memset(&client, 0, sizeof(client));
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd < 0)
{
printf("socket error!\n");
return -1;
}
server.sin_family = AF_INET;
server.sin_port = htons(SERVER_PORT);
server.sin_addr.s_addr = inet_addr(SERVER_IP);
if (bind(listen_fd, (struct sockaddr *)&server, saddrlen) < 0)
{
printf("bind error!\n");
return -1;
}
if (listen(listen_fd, 5) < 0)
{
printf("listen error!\n");
return -1;
}
char rbuf[256] = {0};
int read_size = 0;
while (1)
{
new_fd = accept(listen_fd, (struct sockaddr *)&client, &caddrlen);
if (new_fd < 0)
{
perror("accept");
return -1;
}
printf("new client connected.IP:%s,port:%u\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
while (1)
{
read_size = read(new_fd, rbuf, sizeof(rbuf));
if (read_size < 0)
{
printf("read error!\n");
continue;
}
else if (read_size == 0)
{
printf("client (%d) is closed!\n", new_fd);
close(new_fd);
break;
}
printf("recv:%s\n", rbuf);
}
}
close(listen_fd);
return 0;
}
- 建立一个客户端程序client.c,代码如下:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define SERVER_PORT 6000 // 端口
#define SERVER_IP "192.168.126.128" //服务器IP地址
int main(int argc, const char *argv[])
{
int connect_fd = -1;
struct sockaddr_in server;
socklen_t saddrlen = sizeof(server);
memset(&server, 0, sizeof(server));
connect_fd = socket(AF_INET, SOCK_STREAM, 0);
if (connect_fd < 0)
{
printf("socket error!\n");
return -1;
}
server.sin_family = AF_INET;
server.sin_port = htons(SERVER_PORT);
server.sin_addr.s_addr = inet_addr(SERVER_IP);
if (connect(connect_fd, (struct sockaddr *)&server, saddrlen) < 0)
{
printf("connect failed!\n");
return -1;
}
char buf[256] = {0};
while (1)
{
printf(">");
fgets(buf, sizeof(buf), stdin);
if (strcmp(buf, "quit\n") == 0)
{
printf("client will quit!\n");
break;
}
write(connect_fd, buf, sizeof(buf));
}
close(connect_fd);
return 0;
}
3.编译以上程序,在一个终端窗口中运行server程序,另外打开一个终端窗口,运行client程序。观察程序运行结果。
4.打开第3个终端窗口,运行client窗口,观察程序运行结果。分析:服务器端能同时响应两个客户端的连接请求吗?
PART 2 程序实现
PART 1 中实现的功能是客户端向服务器端发送信息,服务器端接收到信息后显示出来,在理解上述程序的基础上,对程序功能进行扩展,实现如下功能:
(1)服务器端接收到信息后,进行简单的加密处理,然后将加密之后的字符串发回给客户端,客户端将其显示出来。 加密策略为:如果字符为英文字符,则进行大小写转换,如果是数字字符,则将相应的数字加6再取个位数,如果是其他字符,则保留原样。如服务器接收到的字符串为:A1b2D9#6,则加密之后的字符串为:a7B8d5#2
(2)如果服务器端接收的字符串是"time",则不需要进行加密,而是将系统时间发送给客户端,客户端显示收到的信息。
PART 3 扩展部分
使用socket编程实现一个一对一的聊天程序,(以TCP方式通信)基本功能包括:
(1)双方一对一接收,发送文本信息。
(2)将聊天信息记录以文本文件的形式保存在服务器端中,下次登录时,可以显示出前面50条聊天信息。