tcp/UDP学习
原创
©著作权归作者所有:来自51CTO博客作者神秘的逆人的原创作品,请联系作者获取转载授权,否则将追究法律责任
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<errno.h>
#include "my_recv.h" //自定义的头文件
#define SERV_PORT 4507 //服务器的端口
#define LISTENQ 12 //连接请求的队列的最大长度
#define INVALID_USERINFO 'n' //用户信息无效
#define VALID_USERINFO 'y' //用户信息有效
#define USERNAME 0 //接收的是用户名
#define PASSWORD 1 //接收到的是空码
struct userinfo{ //保存用户名和空码的结构体
char username[32];
char password[32];
};
struct userinfo users[]={
{"guangwen", "unix"},
{"lusiyuang", "4508"},
{"panlinbing", "clh"},
{"kairong", "3"},
{" "," "} //以只舍一个空格的字符串作为数组的结束标志
};
//查找用户名是否存在,存在返回该用户名的下标,不存在则返回-1,出错返回-2
int find_name(const char *name)
{
int i;
if(name==NULL){
printf("in find_name,NULL pointer");
return -2;
}
for(i=0;users[i].username[0] !=' ';i++){
if(strcmp(users[i].username,name)==0){
return i;
}
}
return -1;
}
//发送数据
void send_data(int conn_fd,const char *string)
{
if(send(conn_fd,string,strlen(string),0)<0)
my_err("send",__LINE__);
}
int main()
{
int sock_fd,conn_fd;
int optval;
int flag_recv=USERNAME;//标识接收到的用户名还是空码
int ret;
int name_num;
pid_t pid;
socklen_t cli_len;
struct sockaddr_in cli_addr,serv_addr;
char recv_buf[128];
//创建一个TCP套接字
sock_fd=socket(AF_INET,SOCK_STREAM,0);
if(sock_fd<0){
my_err("socket",__LINE__);
}
//设置该套接字使之可以重新绑定端口
optval=1;
if(setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,(void *)&optval,sizeof(int))<0)
my_err("setsockopt",__LINE__);
//初始化服务器端地址结构
memset(&serv_addr,0,sizeof(struct sockaddr_in));
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERV_PORT);
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
//将套接字绑定到本地端口
if(bind(sock_fd,(struct sockaddr *)&serv_addr,sizeof(struct sockaddr_in))<0)
my_err("bind",__LINE__);
//将套接字转化为监听套接字,最大为LISTENQ
if(listen(sock_fd,LISTENQ)<0)
my_err("listen",__LINE__);
cli_len=sizeof(struct sockaddr_in);
while(1)
{
//通过accept接收客户端的连接请求,并返回连接套接字用于收发数据
conn_fd=accept(sock_fd,(struct sockaddr *)&cli_addr,&cli_len);
if(conn_fd<0)
my_err("accept",__LINE__);
printf("accept a new clinet ,ip=%s:\n",inet_ntoa(cli_addr.sin_addr));
//创建一个子进程处理刚刚接收的连接请求
#include<>
if((pid=fork())==0){
while(1){
if((ret=recv(conn_fd,recv_buf,sizeof(recv_buf),0))<0){
perror("recv");
exit(1);
}
recv_buf[ret-1] = '\0';//将数据结束标志‘\n’替换成字符串结束标>志
if(flag_recv==USERNAME){ //接收到的是用户名
name_num=find_name(recv_buf);
switch(name_num){
case -1:
send_data(conn_fd,"n\n");
break;
case -2:
exit(1);
break;
default:
send_data(conn_fd,"y\n");
flag_recv=PASSWORD;
break;
}
}
else if(flag_recv==PASSWORD) { //接收到的是密码
if(strcmp(users[name_num].password,recv_buf)==0){
send_data(conn_fd,"y\n");
send_data(conn_fd,"welcome login my tcp server\n");
printf("%s login\n",users[name_num].username);
break;//跳出while循环
}else
send_data(conn_fd,"n\n");
}
}
close(sock_fd);
close(conn_fd);
exit(0);//结束子进程
} else { //父进程关闭刚刚接收到的连接请求,执行accept等待其他连接请求
close(conn_fd);
}
}
return 0;
}
TCP客户端:my_clience
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<errno.h>
#include<stdio.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include "my_recv.h"
#define INVALID_USERINFO 'n' //用户信息无效
#define VALID_USERINFO 'y' //用户信息有效
//获取用户输入存入到buf,buf的长度为len,用户输入数据以'\n'为结束标志
int get_userinfo(char *buf,int len)
{
int i;
int c;
if(buf==NULL)
{
return -1;
}
i=0;
while(((c=getchar())!='\n')&&(c!=EOF)&&(i<len-2))
{
buf[i++]=c;
}
buf[i++]='\n';
buf[i++]='\0';
return 0;
}
//输入用户名,然后通过fd发送出去
void input_userinfo(int conn_fd,const char *string)
{
char input_buf[32];
char recv_buf[BUFSIZE];
int flag_userinfo;
//输入用户信息直到正确为止
do{
printf("%s:",string);
if(get_userinfo(input_buf,32)<0){
printf("error return from get_userinfo\n");
exit(1);
}
if(send(conn_fd,input_buf,strlen(input_buf),0)<0){
my_err("send",__LINE__);
}
//从连接套接字上读取一次数据
if(my_recv(conn_fd,recv_buf,sizeof(recv_buf))<0){
printf("data is too long\n");
exit(1);
}
if(recv_buf[0]==VALID_USERINFO){
flag_userinfo=VALID_USERINFO;
} else {
printf("%s error,input again,",string);
flag_userinfo=INVALID_USERINFO;
}
} while(flag_userinfo==INVALID_USERINFO);
}
int main(int argc,char **argv)
{
int i;
int ret;
int conn_fd;
int serv_port;
struct sockaddr_in serv_addr;
char recv_buf[BUFSIZE];
//检查参数个数
if(argc!=5){
printf("Usage: [-p] [serv_port] [-a] [serv_address]\n");
exit(1);
}
//初始化服务器端地址结构
memset(&serv_addr,0,sizeof(struct sockaddr_in));
serv_addr.sin_family=AF_INET;
//从命令行获取服务器端的端口与地址
for(i=0;i<argc;i++)
{
if(strcmp("-p",argv[i])==0){
serv_port=atoi(argv[i+1]);
if(serv_port<0||serv_port>65535){
printf("invalid serv_addr.sin_port\n");
exit(1);
} else {
serv_addr.sin_port=htons(serv_port);
}
continue;
}
if(strcmp("-a",argv[i])==0){
if(inet_aton(argv[i+1],&serv_addr.sin_addr)==0){
printf("invalid server ip address\n");
exit(1);
}
continue;
}
}
//检测是否少输入了某一项参数
if(serv_addr.sin_port==0||serv_addr.sin_addr.s_addr==0){
printf("Usage:[-p] [serv_addr.sin_port] [-a] [serv_address]\n");
exit(1);
}
//创建一个套接字
conn_fd=socket(AF_INET,SOCK_STREAM,0);
if(conn_fd<0)
my_err("socket",__LINE__);
//向服务器端发送连接请求
if(connect(conn_fd,(struct sockaddr *)&serv_addr,sizeof(struct sockaddr))<0)
my_err("connect",__LINE__);
//输入用户名和密码
input_userinfo(conn_fd,"username");
input_userinfo(conn_fd,"password");
//读取欢迎信息并打印出来
if((ret=my_recv(conn_fd,recv_buf,sizeof(recv_buf)))<0){
printf("data is too long\n");
exit(1);
}
for(i=0;i<ret;i++){
printf("%c",recv_buf[i]);
}
printf("\n");
close(conn_fd);
return 0;
}
上一篇:init/inittab
下一篇:qt移植到mini2440
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
TCP UDP
TCP协议,传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议。
tcp TCP UDP 客户端 -
TCP/IP学习 1.6传输层(UDP)
用户数据报协议(UDP)提供一种无连接、尽力而为传送的数据包转发服务。
职场 数据 用户 学习 休闲 -
网络通信TCP/UDP——学习笔记
一、网络通信的基本概念1、TCP和UD..
网络通信 TCP UDP Linux 套接字