編程步驟
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;
}