编程步骤
1)调用Socket函数创建套接字文件
2)调用bind函数绑定ip和端口
3)调用listen函数将套接字文件转为被动描述符
4)调用accept函数监听客户连接
5)调用send函数发送数据
6)调用recv函数接收数据
7)调用shutdown函数结束连接
示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <signal.h>
#define SIP "192.168.239.128" //存放服务器固定ip的宏
#define SPROT 5006 //存放服务器进程固定端口的宏
/*封装应用层数据,目前要发送的数据为学生信息*/
typedef struct data
{
unsigned int stu_num;
char stu_nam[50];
}Data;
void print_err(char* str,int line,int err_no) //报错函数
{
printf("%d %s: %s\n",line,str,strerror(err_no));
exit(-1);
}
int cfd = -1;/*通信套接字文件*/
void signal_fun(int signo)
{
if(signo == SIGINT)
{
//断开连接
//close(cfd);
shutdown(cfd,SHUT_RDWR);
exit(0);
}
}
/*次线程用于接收客户端数据 */
void* pth_fun(void* pth_arg)
{
Data stu_cdata = {0};
int ret = -1;
while(1)
{
bzero(&stu_cdata,sizeof(stu_cdata));
ret = recv(cfd,(void*)&stu_cdata,sizeof(stu_cdata),0);
if(ret == -1) print_err("recv error",__LINE__,errno);
else if(ret>0)
{
printf("student number:%d\n",ntohl(stu_cdata.stu_num));
printf("student name:%s\n",stu_cdata.stu_nam);
}
}
}
int main()
{
int ret=-1;
int sockfd=-1;
signal(SIGINT,signal_fun);
/*创建使用TCP协议的套接字文件 */
sockfd = socket(PF_INET,SOCK_STREAM,0 );
if(sockfd == -1) print_err("socket error",__LINE__,errno);
/*调用bind绑定套接字文件/ip/端口*/
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(SPROT);
saddr.sin_addr.s_addr = inet_addr(SIP);
ret = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
if(ret == -1) print_err("bind error",__LINE__,errno);
/*将套接字文件从主动文件描述符变为被动文件描述符,用于被动监听客户的连接 */
ret = listen(sockfd,3);
if(ret == -1) print_err("listen error",__LINE__,errno);
/*调用accept函数 被动监听客户端的三次握手连接 */
struct sockaddr_in clnaddr = {0};
int clnaddr_size = sizeof(clnaddr);
cfd = accept(sockfd,(struct sockaddr *)&clnaddr,&clnaddr_size);
if(cfd == -1) print_err("accept error",__LINE__,errno);
/*打印客户端的IP和端口号 注意要进行端序转换 */
printf("clint_port = %d\n clint_ip = %s\n",ntohs(clnaddr.sin_port),inet_ntoa(clnaddr.sin_addr));
/*创建一个次线程,用于接收客户端的信息*/
pthread_t tid;
ret = pthread_create(&tid,NULL,pth_fun,NULL);
if(ret != 0) print_err("pth_create fail",__LINE__,ret);
/*服务器循环发送数据 */
Data stu_data = {0};
int tmp;
while(1)
{
bzero(&stu_data,sizeof(stu_data));
printf("please input student number:\n");
scanf("%d",&tmp);
/*主机端序转为网络端序 */
stu_data.stu_num = htonl(tmp);
/*char类型的数据不需要转换端序 */
printf("please input student name:\n");
scanf("%s",stu_data.stu_nam);
/*用send函数发送数据 */
ret = send(cfd,(void *)&stu_data,sizeof(stu_data),0);
if(ret == -1) print_err("send error",__LINE__,errno);
}
return 0;
}