服务器
1 #include<head.h>
2 struct Msg
3 {
4 char type;
5 char name[20];
6 char text[100];
7 };
8 typedef struct Node
9 {
10 struct sockaddr_in addr;
11 struct Node *next;
12 }*Linklist;
13 Linklist create_node()
14 {
15 Linklist p=(Linklist)malloc(sizeof(struct Node));
16 if(NULL==p)
17 {
18 return NULL;
19 }
20 p->next=NULL;
21 return p;
22 }
23 Linklist insert_rear(Linklist head,struct sockaddr_in addr)
24 {
25 Linklist s=create_node();
26 if(NULL==s)
27 {
28 return head;
29 }
30 s->addr =addr;
31 if(NULL==head)
32 {
33 head==s;
34 }
35 else
36 {
37 Linklist p=head;
38 while(p->next!=NULL)
39 {
40 p=p->next;
41 }
42 p->next=s;
43 }
44 return head;
45 }
46 int main(int argc, const char *argv[])
47 {
48 if(argc!=3)
49 {
50 printf("请输入ip地址和端口号\n");
51 return -1;
52 }
53
54 //创建套接字
55 int sfd = socket(AF_INET, SOCK_DGRAM, 0);
56 //SOCK_DGRAM:表示使用UDP报式套接字通信
57 if(sfd == -1)
58 {
59 perror("socket error");
60 return -1;
61 }
62 printf("sfd = %d\n", sfd);
63 //绑定
64 //填充地址信息结构体
65 struct sockaddr_in sin;
66 sin.sin_family = AF_INET;
67 sin.sin_port = htons(argv[2]); //端口号
68 sin.sin_addr.s_addr = inet_addr(argv[1]); //ip地址
69 //绑定工作
70 if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) == -1)
71 {
72 perror("bind error");
73 return -1;
74 }
75 //定义变量存放客户端地址信息结构体
76 struct sockaddr_in cin;
77 socklen_t socklen = sizeof(cin);
78 Linklist head=create_node();
79 head->addr=cin;
80 struct Msg msg;
81 pid_t pid=fork();
82 //发送服务器消息
83 if(pid>0)
84 {
85 while(1)
86 {
87 recvfrom(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin));
88 if(msg.type=='L')
89 {
90 printf("%s [%s:%d]登录成功\n",msg.name,inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
91 }
92 if(msg.type=='C')
93 {
94 printf("%s [%s:%d]chat成功\n",msg.name,inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
95 }
96 if(msg.type=='Q')
97 {
98 printf("%s [%s:%d]退出成功\n",msg.name,inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
99 }
100 }
101 }
102 else if(pid==0)
103 {
104 while(1)
105 {
106 recvfrom(sfd,&msg,sizeof(msg),0,(struct sockaddr*)&cin,sizeof(cin));
107 if(msg.type=='L')
108 {
109 char buf[128]="";
110 sprintf(buf,"-----%s登录成功-----\n",msg.name);
111 insert_rear(head,cin);
112 Linklist p=head;
113 while(p->next!=NULL)
114 {
115 sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,socklen);
116 p=p->next;
117 }
118 }
119 if(msg.type=='C')
120 {
121 char sbuf[128]="";
122 sprintf(sbuf,"[%s]:%s\n",msg.name,msg.text);
123 Linklist s=head;
124 while(s->next!=NULL)
125 {
126 sendto(sfd,sbuf,sizeof(sbuf),0,(struct sockaddr*)&cin,socklen);
127 s=s->next;
128 }
129 }
130 if(msg.type=='Q')
131 {
132 char qbuf[128]="";
133 sprintf(qbuf,"-----%s已下线-----\n",msg.name);
134 Linklist s=head;
135 while(s->next!=NULL)
136 {
137 sendto(sfd,qbuf,sizeof(qbuf),0,(struct sockaddr*)&cin,socklen);
138 s=s->next;
139 }
140 }
141 }
142 }
143 else
144 {
145 perror("pid error");
146 return -1;
147 }
148 //4、关闭套接字
149 close(sfd);
150 return 0;
151 }
客户端
1 #include<head.h>
2 struct Msg
3 {
4 char type;
5 char name[20];
6 char text[100];
7 };
8 int main(int argc, const char *argv[])
9 {
10 if(argc!=3)
11 {
12 printf("请输入ip地址和端口号\n");
13 return -1;
14 }
15 //创建用于通信的套接字文件描述符
16 int cfd = socket(AF_INET, SOCK_DGRAM, 0);
17 if(cfd == -1)
18 {
19 perror("socket error");
20 return -1;
21 }
22 //填充服务器的地址信息结构体
23 struct sockaddr_in sin;
24 sin.sin_family = AF_INET;
25 sin.sin_port = htons(argv[2]);
26 sin.sin_addr.s_addr = inet_addr(argv[1]);
27 struct Msg msg;
28 char user[20]="";
29 memset(&msg,0,sizeof(msg));
30 printf("用户名:");
31 fgets(user,sizeof(user),stdin);
32 strcpy(msg.name,user);
33 msg.type='L';
34 sendto(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin));
35 pid_t pid=fork();
36 //发送数据
37 if(pid>0)
38 {
39 while(1)
40 {
41 fgets(msg.text,sizeof(msg.text),stdin);
42 msg.text[strlen(msg.text)-1]='\0';
43 msg.type='C';
44 if((sendto(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin)))==-1)
45 {
46 perror("sendto error");
47 return -1;
48 }
49 if(strcpy(msg.text,"quit")==0)
50 {
51 msg.type='Q';
52 sendto(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin));
53 goto END;
54 }
55 }
56 }
57 //接受数据
58 else if(pid==0)
59 {
60 while(1)
61 {
62 memset(&msg,0,sizeof(msg));
63 if((recvfrom(cfd,&msg,sizeof(msg),0,(struct sockaddr*)&sin,sizeof(sin)))==-1)
64 {
65 perror("recvfrom error");
66 return -1;
67 }
68 if(msg.type=='L')
69 {
70 printf("[%s]上线了\n",msg.name);
71 }
72 if(msg.type=='C')
73 {
74 printf("[%s]:%s\n",msg.name,msg.text);
75 }
76 if(msg.type=='Q')
77 {
78 printf("[%s]下线了\n",msg.name);
79 }
80 }
81 }
82 else
83 {
84 perror("pid error");
85 return -1;
86 }
87 END:
88 //关闭套接字
89 close(cfd);
90 return 0;
91 }