实验5 linux网络编程
题目一
完成基于TCP的客户端和服务器程序编写,要求服务器采用循环方式处理客户端的数据。
server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#define SERVER_PORT 5012
#define SERV_IP="127.0.0.1"
int main(void)
{
int clientSocket = -1,listenSocket = -1;
struct sockaddr_in cliaddr,seraddr;
socklen_t clie_addr_len;
char buf[BUFSIZ];
int n,i,ret;
listenSocket = socket(AF_INET,SOCK_STREAM,0);//用来指定套接字使用的地址格式,通常使用AF_INET IPV4
//指定套接字的类型,若是SOCK_STREAM,则用的是tcp,指定使用的协议类型(当指定套接字类型后,可以设置为0,因为默认为UDP或TCP)
if(-1 == listenSocket){
perror("socket error");
exit(1);
}
else
{
printf("listenSocket = %d
",listenSocket);
}
// bzero(&seraddr,sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(SERVER_PORT);//1024 ~ 49151:普通用户注册的端口号
seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
ret=bind(listenSocket,(struct sockaddr *)&seraddr,sizeof(seraddr));// 绑定这个套节字到一个本地地址
if(ret == -1){
perror("bind error");
exit(1);
}
listen(listenSocket,128);// 进入监听模式,监听队列中允许保持的尚未处理的最大连接数
if(ret == -1){
perror("listen error");
exit(1);
}
clie_addr_len = sizeof(cliaddr);
clientSocket=accept(listenSocket,(struct sockaddr *)&cliaddr,&clie_addr_len);// 接受一个新连接,指向本地数据结构sockaddr_in的指针,
//调用connect()的信息将存储在该结构中,返回一个socket 端口,用来通信
if(clientSocket == -1){
perror("accept error");
exit(1);
}
while(1){
n=read(clientSocket,buf,sizeof(buf));//收
for(i=0;i<n;i++)
buf[i]=toupper(buf[i]);
write(clientSocket,buf,n);//发
}
close(clientSocket);// 关闭套节字
close(listenSocket);
return 0;
}
client.c
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#define SERVER_PORT 5012
#define SERV_IP="127.0.0.1"
int main(void)
{
int clientSocket = -1;
struct sockaddr_in seraddr;
socklen_t serv_addr_len;
char buf[BUFSIZ];
int n;
clientSocket=socket(AF_INET,SOCK_STREAM,0);
// 也可以在这里调用bind函数绑定一个本地地址, 否则系统将会自动安排
bzero(&seraddr,sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(SERVER_PORT);// 注意,这里要填写服务器程序(TCPServer程序)所在机器的IP地址
// 如果你的计算机没有联网,直接使用127.0.0.1即可
seraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(clientSocket,(struct sockaddr *)&seraddr,sizeof(seraddr));
while(1){
fgets(buf,sizeof(buf),stdin);
write(clientSocket,buf,strlen(buf));// 向服务器端发送数据
n=read(clientSocket,buf,sizeof(buf));//从服务器端接收数据
write(1,buf,n);
}
close(clientSocket);// 关闭套节字
return 0;
}
运行截图
题目二
完成基于UDP的客户端和服务器程序编写,要求服务器采用循环方式处理客户端的数据。
udpServer.c
#include<sys/types.h>
#include<sys/socket.h> /*socket() bind()*/
#include<linux/in.h> /*struct sockaddr_in*/
#include<string.h> /*memset*/
#include<stdio.h>
#include<stdlib.h>
void udpserv_echo(int ,struct sockaddr*);
int main(int argc,char *argv[])
{
int s;
struct sockaddr_in addr_ser,addr_clie;
s = socket(AF_INET,SOCK_DGRAM,0);// 生成套接字文件描述符,用来指定套接字使用的地址格式,通常使用AF_INET IPV4
//指定套接字的类型,SOCK_STREAM数据报套接字,无连接,则用的是tcp,指定使用的协议类型(当指定套接字类型后,可以设置为0,因为默认为UDP或TCP);
memset(&addr_ser,0,sizeof(addr_ser));
// 通过struct sockaddr_in 结构设置服务器地址和监听端口
addr_ser.sin_family = AF_INET;
addr_ser.sin_addr.s_addr = htonl(INADDR_ANY);//把unsigned long类型从主机序转换到网络序
addr_ser.sin_port = htons(8888);//把unsigned short类型从主机序转换到网络序
bind(s,(struct sockaddr*)&addr_ser,sizeof(addr_ser));
udpserv_echo(s,(struct sockaddr*)&addr_clie);
return 0;
}
void udpserv_echo(int s,struct sockaddr*addr_clie)
{
char buff[256];
int i=0;
int n;
char str[10];
socklen_t len;
while(1)
{
len = sizeof(*addr_clie);
sprintf(str,"%d",i);//把i转换为字符串
n=recvfrom(s,buff,256,0,addr_clie,&len);//收发数据,用函数send()和recv(),或者read()和write()
strcat(buff,str);//把收到的数据+i再发送到客户端
printf("%s,%s
",str,buff);
sendto(s,buff,n+1,0,addr_clie,len);
i++;
}
}
udpClient.c
#include<sys/types.h>
#include<sys/socket.h> /*socket() bind()*/
#include<linux/in.h> /*struct sockaddr_in*/
#include<string.h> /*memset()*/
#include<stdio.h>
void udpclie(int,struct sockaddr*);
int main(int argc,char *argv[])
{
int s;
struct sockaddr_in addr_ser;
s = socket(AF_INET,SOCK_DGRAM,0);//AF_INET IPV4协议,SOCK_DGRAM UDP协议
memset(&addr_ser,0,sizeof(addr_ser));//清空
addr_ser.sin_family = AF_INET;//IPV4
addr_ser.sin_addr.s_addr = htonl(INADDR_ANY);//将本地地址转换成无符号长整型的网络字节顺序。表示从本机的任一网卡接收数据
addr_ser.sin_port = htons(8888);//指定端口号把unsigned short类型从主机序转换到网络序
udpclie(s,(struct sockaddr*)&addr_ser);
close(s);
return 0;
}
void udpclie(int s,struct sockaddr*to)
{
char buff[256];// = "Hello udp";
struct sockaddr_in from;
socklen_t len = sizeof(*to);
while(1){
gets(buff);//puts(buff);
sendto(s,buff,256,0,to,len);//收发数据,用函数send()和recv(),或者read()和write()
recvfrom(s,buff,sizeof(buff),0,(struct sockaddr*)&from,&len);
printf("recved:%s
",buff);
sleep(2);
}
}
运行截图