# 網路程式設計 HW6
* 本週投影片提到的聊天室延伸功能有:
- [x] 1. 三人交談
- [x] 2. 不雅字馬掉 (Ex: FxxK )
- [x] 3. 當有人說bye,結束此聊天室
- [ ] 4. 語句翻譯
- [x] 5. client設定發言者名後,將來對話顯示發言者
- [ ] 6. 當有人說bye,結束此聊天室
- [ ] 7. 二間聊天室
## 1. 請任選以上二項聊天室延伸功能,實作一個聊天室系統。
* CODE
* Server
```c==
// simple TCP chatroom server
// v3: Not require take turn talking
#include <stdio.h>
#include <winsock.h>
int main(){
SOCKET sd,clnt_sd0,clnt_sd1,clnt_sd2,clnt_sd3;
WSADATA wsadata;
struct sockaddr_in serv,clnt0,clnt1,clnt2,clnt3;
int i,n;
char str[100];
WSAStartup(0x101,&wsadata);
sd = socket(AF_INET, SOCK_STREAM, 0);
serv.sin_family = AF_INET;
serv.sin_port = htons(1234);
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
bind(sd, (struct sockaddr *) &serv, sizeof(serv));
listen(sd,5);
int clnt_len1=sizeof(clnt1);
int clnt_len2=sizeof(clnt2);
int clnt_len3=sizeof(clnt3);
printf("Server waits.\n");
clnt_sd1 = accept(sd, (struct sockaddr *) &clnt1,&clnt_len1 );
printf("(1) 1 connection.\n");
clnt_sd2 = accept(sd, (struct sockaddr *) &clnt2,&clnt_len2 );
printf("(2) 2 connections.\n");
clnt_sd3 = accept(sd, (struct sockaddr *) &clnt3,&clnt_len3 );
printf("(3) 3 connections.\n");
int clnt_len0=sizeof(clnt0);
while(1){
clnt_sd0 = accept(sd, (struct sockaddr *) &clnt0,&clnt_len0 );
n = recv(clnt_sd0,str, 100, 0);
if (n <= 0 ) break;
closesocket(clnt_sd0);
printf("%s\n",str);
send(clnt_sd1,str, strlen(str)+1,0);
send(clnt_sd2,str, strlen(str)+1,0);
send(clnt_sd3,str, strlen(str)+1,0);
char *BYE=strstr(str," : bye");
if(BYE!=NULL)
{
printf("\nBYEEEEE\n");
break;
}
/*
if((str[0]=='b' || str[0]=='B')&& (str[1]=='y' || str[1]=='Y') && (str[2]=='e' || str[2]=='E'))
{
printf("\nBYEEEEEEEE\n");
break;
//closesocket(sd);
}
*/
}
closesocket(sd);
closesocket(clnt_sd0);
closesocket(clnt_sd1);
closesocket(clnt_sd2);
closesocket(clnt_sd3);
WSACleanup();
system("pause");
}
```
* Input
```c==
// simple TCP chat client(1)
// v3: no take turn
#include <stdio.h>
#include <winsock.h>
#include <string.h>
#include <stdlib.h>
/*
#include <iostream>
#include <sstream>
using namespace std;
*/
char *string_concat(char *str1, char *str2) {
// 計算所需的陣列長度
int length=strlen(str1)+strlen(str2)+1;
// 產生新的陣列空間
char *result = (char*)malloc(sizeof(char) * length);
// 複製第一個字串至新的陣列空間
strcpy(result, str1);
// 串接第二個字串至新的陣列空間
strcat(result, str2);
return result;
}
char *str_replace (char *source, char *find, char *rep){
// 搜尋文字的長度
int find_L=strlen(find);
// 替換文字的長度
int rep_L=strlen(rep);
// 結果文字的長度
int length=strlen(source)+1;
// 定位偏移量
int gap=0;
// 建立結果文字,並複製文字
char *result = (char*)malloc(sizeof(char) * length);
strcpy(result, source);
// 尚未被取代的字串
char *former=source;
// 搜尋文字出現的起始位址指標
char *location= strstr(former, find);
// 漸進搜尋欲替換的文字
while(location!=NULL){
// 增加定位偏移量
gap+=(location - former);
// 將結束符號定在搜尋到的位址上
result[gap]='\0';
// 計算新的長度
length+=(rep_L-find_L);
// 變更記憶體空間
result = (char*)realloc(result, length * sizeof(char));
// 替換的文字串接在結果後面
strcat(result, rep);
// 更新定位偏移量
gap+=rep_L;
// 更新尚未被取代的字串的位址
former=location+find_L;
// 將尚未被取代的文字串接在結果後面
strcat(result, former);
// 搜尋文字出現的起始位址指標
location= strstr(former, find);
}
return result;
}
int main(){
SOCKET sd;
WSADATA wsadata;
struct sockaddr_in serv;
int i,n;
char str[100]="I love NP!";
char NAME[100]="";
char SEND[100]="";
WSAStartup(0x101,&wsadata);
serv.sin_family = AF_INET;
serv.sin_port = htons(1234);
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
printf("Enter your name : ");
gets(NAME);
while(1){
sd = socket(AF_INET, SOCK_STREAM, 0);
printf("Input:");
gets(str);
char *name=NAME;
name=string_concat(name," : ");
char* str2=str_replace(str,"fuck","fxxk");
char *SEND=string_concat(name,str2);
connect(sd, (struct sockaddr *) &serv,sizeof(serv) );
send(sd,SEND,strlen(SEND)+1,0);
printf("%s\n",SEND);
//closesocket(sd);
}
WSACleanup();
}
```
* viewer
```c==
// simple TCP chat client viewwer
// v3: two client chat through server
#include <stdio.h>
#include <winsock.h>
int main(){
SOCKET sd;
WSADATA wsadata;
struct sockaddr_in serv;
int i,n;
char str[100]="I love NP!";
WSAStartup(0x101,&wsadata);
sd = socket(AF_INET, SOCK_STREAM, 0);
serv.sin_family = AF_INET;
serv.sin_port = htons(1234);
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sd, (struct sockaddr *) &serv,sizeof(serv) );
printf("Connect to server.\n");
while(1){
memset(str,0,100);
n = recv(sd,str, 100, 0);
if (n <=0) break;
printf("%s\n",str);
}
closesocket(sd);
WSACleanup();
system("pause");
}
```
* 執行結果

## 2. 本週心得
* 請寫下對於本週影片教學和程式作業的適應程度。
本次是目前為止覺得最有趣的作業。
原本想要改用C++寫,一開始執行的很順利,後來突然跳出下圖

跟室友討論後,發現他們也有人有這問題,只好改用C寫了。
###### tags: `網路程式設計`