程序比较简单,不过还是有些需要注意的地方:
1:int main(int argc, char **argv)
在调用程序时可以传入参数,例如
./a.out aaa bbb ccc
上面的都是传入main函数的参数,main函数中的形参argc就是参数的个数,**argv就是传入参数的数组(使用方法argv[index])。在本任务中可实现对ip和端口的设定,argv[0]就是"./a.out" argv[1] 是"aaa"
2:perror ("socket");
这个命令和printf差不多,只是会在print的同时输出最近的错误信息,可以用来打印某些步骤出错(例如socket连接)
3:
serveraddress.sin_family= AF_INET;//ipv4
serveraddress.sin_addr.s_addr= inet_addr("0.0.0.0");//0.0.0.0是监听所有ip
serveraddress.sin_port= htons(atoi(argv[1]));//设置为大端(小端:先存储低位,大端:先存储高位)
4:gets有bug,没有长度限制,可以使用fgets(buf,100,stdin);//获取键盘输入
演示图
客户端:
/*
* @Author: CanEve
* @Date: 2023-05-12 22:52:38
* @LastEditTime: 2023-06-02 05:04:20
* @FilePath: /undefined/home/kali/cprogrames/hqyj_learn/day5/client/tcp_client.c
* @Description: 网络客户端
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv){
if(argc!=3){
printf("usage: %s <host> <port>\n",argv[0]);
return -1;
}
int socket_fd = socket(AF_INET, SOCK_STREAM,0);//使用ipv4
if(-1==socket_fd ){
perror ("socket");//可同时打印最近的报错信息
return -1;
}
struct sockaddr_in serveraddress={0};
serveraddress.sin_family= AF_INET;//ipv4
serveraddress.sin_addr.s_addr= inet_addr(/*"127.0.0.1"*/argv[1]);
serveraddress.sin_port= htons(/*8888*/atoi(argv[2]));//设置为大端(小端:先存储低位,大端:先存储高位,这里统一一下)
int conn_fd=connect(socket_fd,(struct sockaddr *)&serveraddress,sizeof(serveraddress));//连接
if(-1==conn_fd){
perror ("connect");
return -1;
}
while(1){
printf("input : ");//前部提示
fflush(stdout);//刷新缓冲区,printf需要\n刷新
//gets有bug,没有长度限制
char buf[1024];
// gets(buf);
fgets(buf,100,stdin);//获取键盘输入
write(socket_fd,buf,strlen(buf));//发送
if(read(socket_fd,buf,sizeof buf)){//接收
printf(buf);
fflush(stdout);
}
}
close(socket_fd);//关闭socket
return 0;
}
服务端:
/*
* @Author: CanEve
* @Date: 2023-05-13 03:24:43
* @LastEditTime: 2023-06-02 05:32:28
* @FilePath: /day5/server/tcp_server.c
* @Description: tcp server
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//#include "database.h"
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv){
if(argc!=2){
printf("usage: %s <port>\n",argv[0]);
return -1;
}
// MYDATABASE db;
// database_init(&db);
// read_line("save.txt",&db);
int socket_fd = socket(AF_INET, SOCK_STREAM,0);
if(-1==socket_fd ){
perror ("socket");
return -1;
}
struct sockaddr_in serveraddress={0},clientaddr={0};
serveraddress.sin_family= AF_INET;//ipv4
serveraddress.sin_addr.s_addr= inet_addr("0.0.0.0");//0.0.0.0是监听所有ip
serveraddress.sin_port= htons(atoi(argv[1]));//设置为大端(小端:先存储低位,大端:先存储高位)
int conn_fd=bind(socket_fd,(struct sockaddr *)&serveraddress,sizeof(serveraddress));//绑定ip和端口
if(-1==conn_fd){
perror ("connect");
return -1;
}
listen(socket_fd,10);//可接受10个(但不能同时连接)
printf("Server listening on\n");
while(1){//多次连接
int client=accept(socket_fd,NULL,NULL/*(struct sockaddr *)&clientaddr,sizeof clientaddr*/);//等待客户端接入
printf("Client listening on\n");
char buf[1024];
while (1)
{
memset(buf,0,1024);
if(read(client,buf,1024)){
printf("rec -> %s\n",buf);
if(write(client,buf,strlen(buf))<=0){//返回给客户端
break;//客户端断开后等待下一个连接
}
// run_database(buf,client,&db);
}else{
break;//客户端断开后等待下一个连接
}
}
close(client);
}
close(socket_fd);
//write(client,buf,strlen(buf));
// char repeat[1024]={"hello\n"};
// write(client,repeat,6);
return 0;
}
完整代码仓库:https://gitee.com/caneve/opencaneve/tree/main/Linux/tcp_server_client