1. 将TCP的服务器客户端重新写一遍
服务器端Ser.c
#include <myhead.h>
#define ERR_MSG(msg) do{\
fprintf(stderr," %d ",__LINE__);\
perror(msg);\
return -1; \
}while(0)
#define IP "192.168.0.107" //ifconfig查看本机IP
int main(int argc, const char *argv[])
{
//创建流式套接字
//绑定服务器的IP和端口--绑定
//将套接字设置为被动监听状态,监听是否有客户端连接
//有客户端连接后,创建一个新的通信套接字与客户端通信
//接收数据
//发送数据
//关闭文件描述符符
//1.创建流式套接字
int sfd = socket(AF_INET,SOCK_STREAM,0);
if(sfd < 0)
{
ERR_MSG("socket error");
}
//允许端口快速被重用
int reuse = 1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt error");
}
printf("允许端口快速被重用成功\n");
//2.填充服务器的地址信息结构体
struct sockaddr_in sin;
sin.sin_family = AF_INET; //必须填AF_INET
sin.sin_port = htons(8888); //端口号的网络字节序
sin.sin_addr.s_addr = inet_addr(IP); //本机IP的网络字节序
//3.绑定服务器的IP和端口--绑定
if(-1 == bind(sfd,(struct sockaddr*)&sin,sizeof(sin)))
{
ERR_MSG("bind error");
}
printf("bind success\n");
//4.将套接字设置为被动监听状态,监听是否有客户端连接
if(listen(sfd,128) <0 )
{
ERR_MSG("listen error");
}
printf("listen success\n");
//5.有客户端连接后,创建一个新的通信套接字与客户端通信
struct sockaddr_in cin;
socklen_t addrlen =sizeof(cin);
//阻塞函数,阻塞等待客户端连接
//产生新的文件描述符,才是与客户端通信的文件描述符
// while(1){
printf("正在等待客户端连接...\n");
int newfd = accept(sfd,(struct sockaddr*)&cin,&addrlen);
if(newfd < 0)
{
ERR_MSG("accept error");
}
printf("[%s :%d] newfd = %d 客户端连接成功\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd); //网络字节序转换成点分字节序
char buf[128] = "";
ssize_t res = 0;
while(1)
{
//6.接收数据
memset(buf,0,sizeof(buf));
res = recv(newfd,buf,sizeof(buf),0);
if(res == -1)
{
ERR_MSG("recv error");
}
if(res == 0)
{
printf("[%s :%d] newfd = %d 客户端已断开连接.....\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd); //网络字节序转换成点分字节序
break;
}
printf("newfd = %d: %s\n",newfd,buf);
//7.发送数据
strcat(buf,"*_*"); //可以修改为从终端获取
if(-1 == send(newfd,buf,sizeof(buf),0))
{
ERR_MSG("send error");
}
printf("发送成功\n");
}
close(newfd);
// }
//8.关闭文件描述符
close(sfd);
return 0;
}
客户端代码Cli.c:
#include <myhead.h>
#define ERR_MSG(msg) do{\
fprintf(stderr," %d ",__LINE__);\
perror(msg);\
return -1; \
}while(0)
#define IP "192.168.0.107" //ifconfig查看本机IP
#define PORT 8888
int main(int argc, const char *argv[])
{
//创建流式套接字
//绑定服务器的IP和端口--绑定
//将套接字设置为被动监听状态,监听是否有客户端连接
//有客户端连接后,创建一个新的通信套接字与客户端通信
//接收数据
//发送数据
//关闭文件描述符符
//1.创建流式套接字
int sfd = socket(AF_INET,SOCK_STREAM,0);
if(sfd < 0)
{
ERR_MSG("socket error");
}
//允许端口快速被重用
int reuse = 1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt error");
}
printf("允许端口快速被重用成功\n");
//2.填充要连接的服务器的地址信息结构体,给connect函数使用
//需要连接哪个服务器,就填充哪个服务器绑定的地址信息
struct sockaddr_in sin;
sin.sin_family = AF_INET; //必须填AF_INET
sin.sin_port = htons(PORT); //服务器绑定的端口号(网络字节序)
sin.sin_addr.s_addr = inet_addr(IP); //服务器绑定的IP地址(网络字节序)
/*
//3.绑定服务器的IP和端口--非必须绑定:
//若不绑定,操作系统会自动绑定允许环境下的IP地址和随机端口号给客户端
if(-1 == bind(sfd,(struct sockaddr*)&sin,sizeof(sin)))
{
ERR_MSG("bind error");
}
printf("bind success\n");
*/
//4.连接服务器
if(-1 == connect(sfd,(struct sockaddr*)&sin,sizeof(sin)))
{
ERR_MSG("connect error");
}
printf("与服务器连接成功\n");
char buf[128] = "";
ssize_t res = 0;
while(1)
{
//5.发送数据
memset(buf,0,sizeof(buf));
printf("请输入>>>");
fgets(buf,sizeof(buf),stdin); //从终端输入
buf[strlen(buf)-1] = 0;
//对方接收多少字节,发送相同字节
if(-1 == send(sfd,buf,sizeof(buf),0))
{
ERR_MSG("send error");
}
printf("发送成功\n");
//6.接收数据
memset(buf,0,sizeof(buf));
res = recv(sfd,buf,sizeof(buf),0);
if(-1 == res)
{
ERR_MSG("recv error");
}
else if(0 == res)
{
printf("%d服务器断开连接了\n",sfd);
break;
}
printf("%d:%s\n",sfd,buf);
}
//7.关闭文件描述符
close(sfd);
return 0;
}
运行结果如下:
ubuntu@ubuntu:02_TCP$ gcc 01_tcpSer.c -o ser.out
ubuntu@ubuntu:02_TCP$ ./ser.out
允许端口快速被重用成功
bind success
listen success
正在等待客户端连接...
[192.168.0.107 :38832] newfd = 4 客户端连接成功
newfd = 4: summer
发送成功
newfd = 4: beautiful
发送成功
[192.168.0.107 :38832] newfd = 4 客户端已断开连接.....
ubuntu@ubuntu:02_TCP$
ubuntu@ubuntu:02_TCP$ gcc 02_tcpCli.c -o cli.out
ubuntu@ubuntu:02_TCP$ ./cli.out
允许端口快速被重用成功
与服务器连接成功
请输入>>>summer
发送成功
3:summer*_*
请输入>>>beautiful
发送成功
3:beautiful*_*
请输入>>>^C
ubuntu@ubuntu:02_TCP$
2. 自行编写一个客户端代码,能够操作红色手臂移动到16度
1)基于TCP服务器的机械臂,端口号是8888, ip是Windows的ip;
2)点击软件中的开启监听;
3)机械臂需要发送16进制数,共5个字节,协议如下
0xff 0x02 x y 0xff
0xff:起始结束协议,固定的; 0x02:控制机械手臂协议,固定的;
x:指定要操作的机械臂 0x00 红色摆臂 0x01 蓝色摆臂 y:指定角度
客户端代码如下Cli.c:
#include <myhead.h>
#define ERR_MSG(msg) do{\
fprintf(stderr," %d ",__LINE__);\
perror(msg);\
return -1; \
}while(0)
#define IP "192.168.0.104" //服务器IP地址(Windows)
#define PORT 8888
int main(int argc, const char *argv[])
{
//1.创建流式套接字
int sfd = socket(AF_INET,SOCK_STREAM,0);
if(sfd < 0)
{
ERR_MSG("socket error");
}
//允许端口快速被重用
int reuse = 1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt error");
}
printf("允许端口快速被重用成功\n");
//2.填充要连接的服务器的地址信息结构体,给connect函数使用
//需要连接哪个服务器,就填充哪个服务器绑定的地址信息
struct sockaddr_in sin;
sin.sin_family = AF_INET; //必须填AF_INET
sin.sin_port = htons(PORT); //服务器绑定的端口号(网络字节序)
sin.sin_addr.s_addr = inet_addr(IP); //服务器绑定的IP地址(网络字节序)
//3.连接服务器
if(-1 == connect(sfd,(struct sockaddr*)&sin,sizeof(sin)))
{
ERR_MSG("connect error");
}
printf("与服务器连接成功\n");
char buf[5] = {0xff,0x02,0x00,0x10,0xff};
ssize_t res = 0;
while(1)
{
//4.发送数据
if(-1 == send(sfd,buf,sizeof(buf),0))
{
ERR_MSG("send error");
}
sleep(1);
printf("发送红色要比移动到16度成功\n");
}
//5.关闭文件描述符
close(sfd);
return 0;
}
运行结果如下:
ubuntu@ubuntu:02_TCP$ ./a.out
允许端口快速被重用成功
与服务器连接成功
发送红色要比移动到16度成功
发送红色要比移动到16度成功