整体设计: 在客户端,输入小写字母,服务器返回大写字母。
服务器就是本机,(本地服务器),用127.0.0.1测试。
?
本节对应视频:B站 C++就业班28_哔哩哔哩_bilibili
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include<netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <ctype.h> //最后这个是toupper 转换为大写字母的
int main() {
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if (sfd <0){
printf("socket fun error/n");
return -1;
}
//定义一个地址结gou体
struct sockaddr_in myad;
//清空 memory
bzero(&myad, sizeof(myad));
myad.sin_family =AF_INET;
myad.sin_port =htons(8888);
myad.sin_addr.s_addr = htonl (INADDR_ANY);
int ret = bind(sfd, (struct sockaddr *)&myad, sizeof(myad));
if (ret<0) {
printf("bind error/n");
return -1;
}
//将socket从主动变为被动(服务器必备),这样可以监听来自客户的请求
listen( sfd,128); //后面数字随笔写?
int newfd= accept(sfd,NULL,NULL);
//为什么传null 因为从谁来的,还不知道,一会儿改写,让这个函数能打印客户端ip地址
if (newfd <0) {
printf("服务端,accept error、\n");
return -1;
}
// printf("服务器端,get connect:%s\n",inet_ntoa(c_addr.sin_addr));
//把客户端发送过来的数据读出来
int i =0;
int n =0;
char buf[1024];
while (1 ){
memset(buf,0x00,sizeof(buf));
n = read (newfd,buf,sizeof(buf));
if (n<=0){
printf("客户端已关闭,或者读到的字符为0/n");
break;
}
for (i=0;i<n;i++){
buf[i] =toupper(buf[i]);
}
printf("服务器端。客户端的数据变成大写了\n");
//把数据传回客户端,变成大写了已经
write (newfd, buf, n);
}
close(newfd);
close(sfd);
return 0;
}
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include<netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int main() {
int sfd2 = socket(AF_INET, SOCK_STREAM, 0);
if (sfd2 <0){
printf("socket fun error/n");
return -1;
}
//定义一个地址结gou体,服务器地址。
struct sockaddr_in seradd;
//清空 memory
bzero(&seradd, sizeof(seradd));
seradd.sin_family =AF_INET;
seradd.sin_port = htons(8888);
int s = inet_pton( AF_INET,"127.0.0.1",&seradd.sin_addr.s_addr);
if (s <= 0) {
if (s == 0)
fprintf(stderr, "Not in presentation format");
else
perror("inet_pton");
exit(EXIT_FAILURE);
}
int ret333 = connect(sfd2,(struct sockaddr* )&seradd,sizeof(seradd));
if (ret333<0){
printf("connect error/n");
return -1;
}
int n1 =0, n2=0;
char buf[256];
while (1 ){
memset(buf,0x00,sizeof(buf));
//从电脑键盘输入数据
printf("客户端please type in a word,小写字母\n");
n1 =read (STDIN_FILENO,buf,sizeof(buf));
//发送数据给服务器
write(sfd2,buf,n1);
//读取服务器返回的数据
memset(buf,0x00,sizeof(buf));
n2 = read (sfd2,buf,sizeof(buf));
printf("客户端,接受到的数据为%s\n", buf);
if (n2<=0){
printf("server已关闭,或者读到的字符为0/n");
break;
}
}
close(sfd2);
return 0;
}
?刚才accept函数第二三个参数都是iNULL? 现在再来看一下accept函数
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
? ? ? 从所有请求pending (悬而未决)的请求连接的队列中,找出第一个出来,获得一个新的文件描述符
? ? ? ?addr是传出参数,保留客户的地址,所以这是客户地址
? ? ? ?第三个参数,是传入传出参数,是地址长度,需要先制作出来,再&取地址
? ?//将网络大端模式的地址,转化为字符串
? ? const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
注意,这个“大端格式的地址”指的是32位IP ,而sockaddr_in结构体里面包含很多东西,ip地址只是结构体成员之一
不要混淆,inet_ntop第二个参数别写成&addr结构体 ??
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include<netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <ctype.h>
int main() {
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if (sfd <0){
printf("socket fun error/n");
return -1;
}
//定义一个地址结gou体
struct sockaddr_in myad;
//清空 memory
bzero(&myad, sizeof(myad));
myad.sin_family =AF_INET;
myad.sin_port =htons(8888);
myad.sin_addr.s_addr = htonl (INADDR_ANY);
int ret = bind(sfd, (struct sockaddr *)&myad, sizeof(myad));
if (ret<0) {
printf("bind error/n");
return -1;
}
//将socket从主动变为被动(服务器必备),这样可以监听来自客户的请求
listen(sfd,128);
//定义一个地址结gou体接受客户端地址结构体
struct sockaddr_in dst;
bzero(&myad, sizeof(myad));
dst.sin_family =AF_INET;
dst.sin_port =htons(8888);
socklen_t dstleng = sizeof(dst);
//为什么写这个,因为accept第三个参数也是指针,只能先制作出来
int newfd = accept (sfd, (struct sockaddr* )&dst, &dstleng);
if (newfd <0) {
printf("服务端,accept error、\n");
return -1;
}
char addstring[128];
memset(addstring, 0x00,128);
printf("服务器端,get connect,客户端地址是:\n");
printf("IP:%s,PORT: %d\n", inet_ntop(AF_INET, &dst.sin_addr.s_addr,addstring,sizeof(addstring)), ntohs(dst.sin_port));
//把客户端发送过来的数据读出来
int i =0;
int n =0;
char buf[1024];
while (1 ){
memset(buf,0x00,sizeof(buf));
n = read (newfd,buf,sizeof(buf));
if (n<=0){
printf("客户端已关闭,或者读到的字符为0/n");
break;
}
for (i=0;i<n;i++){
buf[i] =toupper(buf[i]);
}
printf("服务器端。客户端的数据变成大写了\n");
//把数据传回客户端,变成大写了已经
write (newfd, buf, n);
}
close(newfd);
close(sfd);
return 0;
}